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

600 lines
20 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file trigger_decoder.cpp
*
* @date Dec 24, 2013
2015-12-31 13:02:30 -08:00
* @author Andrey Belomutskiy, (c) 2012-2016
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/>.
*/
#include "main.h"
#if EFI_SHAFT_POSITION_INPUT || defined(__DOXYGEN__)
#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"
2015-09-10 19:01:35 -07:00
#include "trigger_subaru.h"
2015-09-19 16:01:46 -07:00
#include "trigger_nissan.h"
2015-12-14 18:01:30 -08:00
#include "trigger_toyota.h"
2015-12-27 12:02:51 -08:00
#include "trigger_rover.h"
2015-07-10 06:01:56 -07:00
#include "trigger_structure.h"
#include "efiGpio.h"
#include "engine.h"
2015-09-12 18:03:09 -07:00
#include "engine_math.h"
2015-09-13 13:01:38 -07:00
#include "trigger_central.h"
2015-09-23 18:02:33 -07:00
#include "trigger_simulator.h"
2015-09-12 18:03:09 -07:00
2015-09-13 09:01:42 -07:00
#if EFI_SENSOR_CHART || defined(__DOXYGEN__)
2015-09-12 18:03:09 -07:00
#include "sensor_chart.h"
#endif
2015-07-10 06:01:56 -07:00
static OutputPin triggerDecoderErrorPin;
EXTERN_ENGINE
;
static cyclic_buffer<int> errorDetection;
2015-09-05 20:02:46 -07:00
#if ! EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
bool printTriggerDebug = false;
float actualSynchGap;
#endif /* ! EFI_PROD_CODE */
static Logging * logger;
efitick_t lastDecodingErrorTime = US2NT(-10000000LL);
2015-09-25 06:06:35 -07:00
// the boolean flag is a performance optimization so that complex comparison is avoided if no error
2016-01-11 14:01:33 -08:00
bool someSortOfTriggerError = false;
2015-07-10 06:01:56 -07:00
/**
* @return TRUE is something is wrong with trigger decoding
*/
2016-01-11 14:01:33 -08:00
bool isTriggerDecoderError(void) {
2015-07-10 06:01:56 -07:00
return errorDetection.sum(6) > 4;
}
2016-01-11 14:01:33 -08:00
bool TriggerState::isValidIndex(DECLARE_ENGINE_PARAMETER_F) {
2015-09-24 19:02:47 -07:00
return currentCycle.current_index < TRIGGER_SHAPE(size);
}
2015-07-10 06:01:56 -07:00
float TriggerState::getTriggerDutyCycle(int index) {
float time = prevTotalTime[index];
return 100 * time / prevCycleDuration;
}
static trigger_wheel_e eventIndex[6] = { T_PRIMARY, T_PRIMARY, T_SECONDARY, T_SECONDARY, T_CHANNEL_3, T_CHANNEL_3 };
2015-10-31 13:02:10 -07:00
//static trigger_value_e eventType[6] = { TV_FALL, TV_RISE, TV_FALL, TV_RISE, TV_FALL, TV_RISE };
2015-07-10 06:01:56 -07:00
#define getCurrentGapDuration(nowNt) \
(isFirstEvent ? 0 : (nowNt) - toothed_previous_time)
#define nextTriggerEvent() \
{ \
2015-09-12 13:01:43 -07:00
uint32_t prevTime = currentCycle.timeOfPreviousEventNt[triggerWheel]; \
2015-07-10 06:01:56 -07:00
if (prevTime != 0) { \
/* even event - apply the value*/ \
2015-09-08 20:01:07 -07:00
currentCycle.totalTimeNt[triggerWheel] += (nowNt - prevTime); \
currentCycle.timeOfPreviousEventNt[triggerWheel] = 0; \
2015-07-10 06:01:56 -07:00
} else { \
/* odd event - start accumulation */ \
2015-09-08 20:01:07 -07:00
currentCycle.timeOfPreviousEventNt[triggerWheel] = nowNt; \
2015-07-10 06:01:56 -07:00
} \
2016-02-27 20:03:34 -08:00
if (engineConfiguration->useOnlyRisingEdgeForTrigger) {currentCycle.current_index++;} \
2015-09-08 20:01:07 -07:00
currentCycle.current_index++; \
2015-07-10 06:01:56 -07:00
}
#define nextRevolution() { \
if (cycleCallback != NULL) { \
cycleCallback(this); \
} \
2015-09-08 20:01:07 -07:00
memcpy(prevTotalTime, currentCycle.totalTimeNt, sizeof(prevTotalTime)); \
2015-07-10 06:01:56 -07:00
prevCycleDuration = nowNt - startOfCycleNt; \
startOfCycleNt = nowNt; \
2015-09-08 20:01:07 -07:00
resetCurrentCycleState(); \
2015-07-10 06:01:56 -07:00
totalRevolutionCounter++; \
runningRevolutionCounter++; \
totalEventCountBase += TRIGGER_SHAPE(size); \
}
/**
* @brief Trigger decoding happens here
2015-08-22 08:02:10 -07:00
* This method is invoked every time we have a fall or rise on one of the trigger sensors.
2015-07-10 06:01:56 -07:00
* This method changes the state of trigger_state_s data structure according to the trigger event
2015-08-22 08:02:10 -07:00
* @param signal type of event which just happened
* @param nowNt current time
2015-07-10 06:01:56 -07:00
*/
void TriggerState::decodeTriggerEvent(trigger_event_e const signal, efitime_t nowNt DECLARE_ENGINE_PARAMETER_S) {
2016-02-27 20:03:34 -08:00
efiAssertVoid(signal <= SHAFT_3RD_RISING, "unexpected signal");
2015-07-10 06:01:56 -07:00
trigger_wheel_e triggerWheel = eventIndex[signal];
2016-02-27 20:03:34 -08:00
if (!engineConfiguration->useOnlyRisingEdgeForTrigger && curSignal == prevSignal) {
2015-07-10 06:01:56 -07:00
orderingErrorCounter++;
}
prevSignal = curSignal;
curSignal = signal;
2015-09-08 20:01:07 -07:00
currentCycle.eventCount[triggerWheel]++;
2015-07-10 06:01:56 -07:00
efitime_t currentDurationLong = getCurrentGapDuration(nowNt);
/**
* For performance reasons, we want to work with 32 bit values. If there has been more then
* 10 seconds since previous trigger event we do not really care.
*/
currentDuration =
currentDurationLong > 10 * US2NT(US_PER_SECOND_LL) ? 10 * US2NT(US_PER_SECOND_LL) : currentDurationLong;
2016-01-11 14:01:33 -08:00
bool isPrimary = triggerWheel == T_PRIMARY;
2015-07-15 20:07:51 -07:00
2015-07-10 06:01:56 -07:00
if (isLessImportant(signal)) {
2015-09-13 07:01:39 -07:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
if (printTriggerDebug) {
2015-09-22 20:01:31 -07:00
printf("%s isLessImportant %s %d\r\n",
2015-07-10 06:01:56 -07:00
getTrigger_type_e(engineConfiguration->trigger.type),
2015-09-22 20:01:31 -07:00
getTrigger_event_e(signal),
nowNt);
2015-07-10 06:01:56 -07:00
}
#endif
/**
* For less important events we simply increment the index.
*/
nextTriggerEvent()
;
2015-07-15 21:07:25 -07:00
if (TRIGGER_SHAPE(gapBothDirections) && considerEventForGap()) {
2015-07-10 06:01:56 -07:00
isFirstEvent = false;
2015-12-27 13:02:44 -08:00
thirdPreviousDuration = durationBeforePrevious;
2015-09-11 22:02:28 -07:00
durationBeforePrevious = toothed_previous_duration;
toothed_previous_duration = currentDuration;
2015-07-10 06:01:56 -07:00
toothed_previous_time = nowNt;
}
2015-09-13 13:01:38 -07:00
} else {
2015-07-10 06:01:56 -07:00
2015-09-22 20:01:31 -07:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
if (printTriggerDebug) {
printf("%s event %s %d\r\n",
getTrigger_type_e(engineConfiguration->trigger.type),
getTrigger_event_e(signal),
nowNt);
}
#endif
2015-09-23 20:01:40 -07:00
isFirstEvent = false;
2015-07-10 06:01:56 -07:00
// todo: skip a number of signal from the beginning
2015-09-13 07:01:39 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
// scheduleMsg(&logger, "from %f to %f %d %d", triggerConfig->syncRatioFrom, triggerConfig->syncRatioTo, currentDuration, shaftPositionState->toothed_previous_duration);
// scheduleMsg(&logger, "ratio %f", 1.0 * currentDuration/ shaftPositionState->toothed_previous_duration);
#else
2015-09-23 20:01:40 -07:00
if (toothed_previous_duration != 0) {
2015-07-10 06:01:56 -07:00
// printf("ratio %f: cur=%d pref=%d\r\n", 1.0 * currentDuration / shaftPositionState->toothed_previous_duration,
// currentDuration, shaftPositionState->toothed_previous_duration);
2015-09-23 20:01:40 -07:00
}
2015-07-10 06:01:56 -07:00
#endif
2016-01-11 14:01:33 -08:00
bool isSynchronizationPoint;
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
if (TRIGGER_SHAPE(isSynchronizationNeeded)) {
/**
* Here I prefer to have two multiplications instead of one division, that's a micro-optimization
*/
2015-12-27 13:02:44 -08:00
isSynchronizationPoint =
currentDuration > toothed_previous_duration * TRIGGER_SHAPE(syncRatioFrom)
2015-09-23 20:01:40 -07:00
&& currentDuration < toothed_previous_duration * TRIGGER_SHAPE(syncRatioTo)
&& toothed_previous_duration > durationBeforePrevious * TRIGGER_SHAPE(secondSyncRatioFrom)
&& toothed_previous_duration < durationBeforePrevious * TRIGGER_SHAPE(secondSyncRatioTo)
2015-12-27 13:02:44 -08:00
// this is getting a little out of hand, any ideas?
&& durationBeforePrevious > thirdPreviousDuration * TRIGGER_SHAPE(thirdSyncRatioFrom)
&& durationBeforePrevious < thirdPreviousDuration * TRIGGER_SHAPE(thirdSyncRatioTo)
;
2015-07-10 06:01:56 -07:00
2015-09-11 22:02:28 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-09-25 06:06:35 -07:00
if (engineConfiguration->isPrintTriggerSynchDetails || someSortOfTriggerError) {
2015-07-10 06:01:56 -07:00
#else
2015-09-23 20:01:40 -07:00
if (printTriggerDebug) {
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
2015-09-23 20:01:40 -07:00
float gap = 1.0 * currentDuration / toothed_previous_duration;
2015-09-25 06:06:35 -07:00
float prevGap = 1.0 * toothed_previous_duration / durationBeforePrevious;
2015-12-27 13:02:44 -08:00
float gap3 = 1.0 * durationBeforePrevious / thirdPreviousDuration;
2015-09-11 22:02:28 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2016-01-30 19:03:36 -08:00
scheduleMsg(logger, "gap=%f/%f/%f @ %d while expected %f/%f and %f/%f error=%d",
gap, prevGap, gap3,
currentCycle.current_index,
TRIGGER_SHAPE(syncRatioFrom), TRIGGER_SHAPE(syncRatioTo),
TRIGGER_SHAPE(secondSyncRatioFrom), TRIGGER_SHAPE(secondSyncRatioTo), someSortOfTriggerError);
2015-07-10 06:01:56 -07:00
#else
2015-09-23 20:01:40 -07:00
actualSynchGap = gap;
2015-12-27 13:02:44 -08:00
print("current gap %f/%f/%f c=%d prev=%d\r\n", gap, prevGap, gap3, currentDuration, toothed_previous_duration);
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
2015-09-23 20:01:40 -07:00
}
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
} else {
/**
* in case of noise the counter could be above the expected number of events
*/
2016-02-27 20:03:34 -08:00
int d = engineConfiguration->useOnlyRisingEdgeForTrigger ? 2 : 1;
2015-09-23 20:01:40 -07:00
isSynchronizationPoint = !shaft_is_synchronized || (currentCycle.current_index >= TRIGGER_SHAPE(size) - d);
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
}
2015-07-10 06:01:56 -07:00
2015-09-13 07:01:39 -07:00
#if EFI_UNIT_TEST || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
if (printTriggerDebug) {
printf("%s isSynchronizationPoint=%d index=%d %s\r\n",
getTrigger_type_e(engineConfiguration->trigger.type),
2015-09-08 20:01:07 -07:00
isSynchronizationPoint, currentCycle.current_index,
2015-07-10 06:01:56 -07:00
getTrigger_event_e(signal));
}
#endif
2015-09-23 20:01:40 -07:00
if (isSynchronizationPoint) {
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
/**
* We can check if things are fine by comparing the number of events in a cycle with the expected number of event.
*/
bool isDecodingError = currentCycle.eventCount[0] != TRIGGER_SHAPE(expectedEventCount[0])
|| currentCycle.eventCount[1] != TRIGGER_SHAPE(expectedEventCount[1])
|| currentCycle.eventCount[2] != TRIGGER_SHAPE(expectedEventCount[2]);
triggerDecoderErrorPin.setValue(isDecodingError);
if (isDecodingError) {
lastDecodingErrorTime = getTimeNowNt();
2015-09-25 06:06:35 -07:00
someSortOfTriggerError = true;
2015-09-23 20:01:40 -07:00
totalTriggerErrorCounter++;
2015-09-25 06:06:35 -07:00
if (engineConfiguration->isPrintTriggerSynchDetails || someSortOfTriggerError) {
2015-09-13 07:01:39 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-09-23 20:01:40 -07:00
scheduleMsg(logger, "error: synchronizationPoint @ index %d expected %d/%d/%d got %d/%d/%d",
currentCycle.current_index, TRIGGER_SHAPE(expectedEventCount[0]),
TRIGGER_SHAPE(expectedEventCount[1]), TRIGGER_SHAPE(expectedEventCount[2]),
currentCycle.eventCount[0], currentCycle.eventCount[1], currentCycle.eventCount[2]);
2015-07-10 06:01:56 -07:00
#endif /* EFI_PROD_CODE */
2015-09-23 20:01:40 -07:00
}
2015-07-10 06:01:56 -07:00
}
2015-09-23 20:01:40 -07:00
errorDetection.add(isDecodingError);
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
if (isTriggerDecoderError()) {
warning(OBD_PCM_Processor_Fault, "trigger decoding issue. expected %d/%d/%d got %d/%d/%d",
TRIGGER_SHAPE(expectedEventCount[0]), TRIGGER_SHAPE(expectedEventCount[1]),
TRIGGER_SHAPE(expectedEventCount[2]), currentCycle.eventCount[0], currentCycle.eventCount[1],
currentCycle.eventCount[2]);
}
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
shaft_is_synchronized = true;
// this call would update duty cycle values
nextTriggerEvent()
;
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
nextRevolution();
} else {
nextTriggerEvent()
;
}
2015-07-10 06:01:56 -07:00
2015-12-27 13:02:44 -08:00
thirdPreviousDuration = durationBeforePrevious;
2015-09-23 20:01:40 -07:00
durationBeforePrevious = toothed_previous_duration;
toothed_previous_duration = currentDuration;
toothed_previous_time = nowNt;
2015-09-13 13:01:38 -07:00
}
2015-09-24 19:02:47 -07:00
if (!isValidIndex(PASS_ENGINE_PARAMETER_F)) {
2016-04-09 16:02:08 -07:00
warning(OBD_PCM_Processor_Fault, "sync error: index #%d above total size %d", currentCycle.current_index, TRIGGER_SHAPE(size));
2015-09-25 06:06:35 -07:00
lastDecodingErrorTime = getTimeNowNt();
someSortOfTriggerError = true;
}
if (someSortOfTriggerError) {
if (getTimeNowNt() - lastDecodingErrorTime > US2NT(US_PER_SECOND_LL)) {
someSortOfTriggerError = false;
}
2015-09-24 19:02:47 -07:00
}
2016-01-30 19:03:36 -08:00
if (ENGINE(sensorChartMode) == SC_RPM_ACCEL || ENGINE(sensorChartMode) == SC_DETAILED_RPM) {
2015-09-13 13:01:38 -07:00
angle_t currentAngle = TRIGGER_SHAPE(eventAngles[currentCycle.current_index]);
// todo: make this '90' depend on cylinder count?
angle_t prevAngle = currentAngle - 90;
fixAngle(prevAngle);
2015-09-13 15:01:23 -07:00
// todo: prevIndex should be pre-calculated
int prevIndex = TRIGGER_SHAPE(triggerIndexByAngle[(int)prevAngle]);
2015-09-13 13:01:38 -07:00
// now let's get precise angle for that event
prevAngle = TRIGGER_SHAPE(eventAngles[prevIndex]);
2016-01-24 22:02:55 -08:00
// todo: re-implement this as a subclass. we need two instances of
// uint32_t time = nowNt - timeOfLastEvent[prevIndex];
2015-09-13 13:01:38 -07:00
angle_t angleDiff = currentAngle - prevAngle;
// todo: angle diff should be pre-calculated
fixAngle(angleDiff);
2016-01-24 22:02:55 -08:00
// float r = (60000000.0 / 360 * US_TO_NT_MULTIPLIER) * angleDiff / time;
2015-09-13 13:01:38 -07:00
#if EFI_SENSOR_CHART || defined(__DOXYGEN__)
2015-09-13 15:01:23 -07:00
if (boardConfiguration->sensorChartMode == SC_DETAILED_RPM) {
2016-01-24 22:02:55 -08:00
// scAddData(currentAngle, r);
2015-09-13 15:01:23 -07:00
} else {
2016-01-24 22:02:55 -08:00
// scAddData(currentAngle, r / instantRpmValue[prevIndex]);
2015-09-13 15:01:23 -07:00
}
2015-09-13 13:01:38 -07:00
#endif
2016-01-24 22:02:55 -08:00
// instantRpmValue[currentCycle.current_index] = r;
// timeOfLastEvent[currentCycle.current_index] = nowNt;
2015-09-13 13:01:38 -07:00
}
2015-07-10 06:01:56 -07:00
}
2016-01-14 21:01:42 -08:00
angle_t getEngineCycle(operation_mode_e operationMode) {
2015-07-10 06:01:56 -07:00
return operationMode == TWO_STROKE ? 360 : 720;
}
2015-09-23 20:01:40 -07:00
void addSkippedToothTriggerEvents(trigger_wheel_e wheel, TriggerShape *s, int totalTeethCount, int skippedCount,
float toothWidth, float offset, float engineCycle, float filterLeft, float filterRight) {
2015-07-10 06:01:56 -07:00
efiAssertVoid(totalTeethCount > 0, "total count");
efiAssertVoid(skippedCount >= 0, "skipped count");
for (int i = 0; i < totalTeethCount - skippedCount - 1; i++) {
float angleDown = engineCycle / totalTeethCount * (i + (1 - toothWidth));
float angleUp = engineCycle / totalTeethCount * (i + 1);
2015-10-31 13:02:10 -07:00
s->addEvent(offset + angleDown, wheel, TV_RISE, filterLeft, filterRight);
s->addEvent(offset + angleUp, wheel, TV_FALL, filterLeft, filterRight);
2015-07-10 06:01:56 -07:00
}
2015-09-23 20:01:40 -07:00
float angleDown = engineCycle / totalTeethCount * (totalTeethCount - skippedCount - 1 + (1 - toothWidth));
2015-10-31 13:02:10 -07:00
s->addEvent(offset + angleDown, wheel, TV_RISE, filterLeft, filterRight);
s->addEvent(offset + engineCycle, wheel, TV_FALL, filterLeft, filterRight);
2015-07-10 06:01:56 -07:00
}
void initializeSkippedToothTriggerShapeExt(TriggerShape *s, int totalTeethCount, int skippedCount,
operation_mode_e operationMode) {
efiAssertVoid(totalTeethCount > 0, "totalTeethCount is zero");
2015-10-30 16:06:55 -07:00
efiAssertVoid(s != NULL, "TriggerShape is NULL");
s->initialize(operationMode, false);
2015-07-10 06:01:56 -07:00
s->setTriggerSynchronizationGap(skippedCount + 1);
s->isSynchronizationNeeded = (skippedCount != 0);
addSkippedToothTriggerEvents(T_PRIMARY, s, totalTeethCount, skippedCount, 0.5, 0, getEngineCycle(operationMode),
2015-09-23 20:01:40 -07:00
NO_LEFT_FILTER, NO_RIGHT_FILTER);
2015-07-10 06:01:56 -07:00
}
static void configureOnePlusOne(TriggerShape *s, operation_mode_e operationMode) {
float engineCycle = getEngineCycle(operationMode);
2015-10-29 11:02:52 -07:00
s->initialize(FOUR_STROKE_CAM_SENSOR, true);
2015-07-10 06:01:56 -07:00
2015-10-31 13:02:10 -07:00
s->addEvent(180, T_PRIMARY, TV_RISE);
s->addEvent(360, T_PRIMARY, TV_FALL);
2015-07-10 06:01:56 -07:00
2015-10-31 13:02:10 -07:00
s->addEvent(540, T_SECONDARY, TV_RISE);
s->addEvent(720, T_SECONDARY, TV_FALL);
2015-07-10 06:01:56 -07:00
s->isSynchronizationNeeded = false;
}
static void configureOnePlus60_2(TriggerShape *s, operation_mode_e operationMode) {
2015-10-29 11:02:52 -07:00
s->initialize(FOUR_STROKE_CAM_SENSOR, true);
2015-07-10 06:01:56 -07:00
int totalTeethCount = 60;
int skippedCount = 2;
2015-10-31 13:02:10 -07:00
s->addEvent(2, T_PRIMARY, TV_RISE);
2015-07-10 06:01:56 -07:00
addSkippedToothTriggerEvents(T_SECONDARY, s, totalTeethCount, skippedCount, 0.5, 0, 360, 2, 20);
2015-10-31 13:02:10 -07:00
s->addEvent(20, T_PRIMARY, TV_FALL);
2015-07-10 06:01:56 -07:00
addSkippedToothTriggerEvents(T_SECONDARY, s, totalTeethCount, skippedCount, 0.5, 0, 360, 20, NO_RIGHT_FILTER);
addSkippedToothTriggerEvents(T_SECONDARY, s, totalTeethCount, skippedCount, 0.5, 360, 360, NO_LEFT_FILTER,
2015-09-23 20:01:40 -07:00
NO_RIGHT_FILTER);
2015-07-10 06:01:56 -07:00
s->isSynchronizationNeeded = false;
}
2016-01-26 16:02:54 -08:00
static TriggerState state CCM_OPTIONAL;
2015-07-10 06:01:56 -07:00
/**
* External logger is needed because at this point our logger is not yet initialized
*/
void TriggerShape::initializeTriggerShape(Logging *logger DECLARE_ENGINE_PARAMETER_S) {
2016-01-09 08:01:43 -08:00
const trigger_config_s *triggerConfig = &engineConfiguration->trigger;
2015-09-13 07:01:39 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
efiAssertVoid(getRemainingStack(chThdSelf()) > 256, "init t");
2016-01-09 08:01:43 -08:00
scheduleMsg(logger, "initializeTriggerShape(%s/%d)", getTrigger_type_e(triggerConfig->type), (int) triggerConfig->type);
2015-07-10 06:01:56 -07:00
#endif
2015-09-13 07:01:39 -07:00
TriggerShape *triggerShape = this;
2015-07-10 06:01:56 -07:00
switch (triggerConfig->type) {
case TT_TOOTHED_WHEEL:
initializeSkippedToothTriggerShapeExt(triggerShape, triggerConfig->customTotalToothCount,
triggerConfig->customSkippedToothCount, engineConfiguration->operationMode);
break;
case TT_MAZDA_MIATA_NA:
2015-10-10 13:01:25 -07:00
initializeMazdaMiataNaShape(triggerShape PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
break;
case TT_MAZDA_MIATA_NB:
2015-10-10 13:01:25 -07:00
initializeMazdaMiataNbShape(triggerShape PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
break;
case TT_DODGE_NEON_1995:
2015-10-10 13:01:25 -07:00
configureNeon1995TriggerShape(triggerShape PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
break;
2015-09-05 20:02:46 -07:00
case TT_DODGE_STRATUS:
2015-10-10 13:01:25 -07:00
configureDodgeStratusTriggerShape(triggerShape PASS_ENGINE_PARAMETER);
2015-09-05 20:02:46 -07:00
break;
2015-07-10 06:01:56 -07:00
case TT_DODGE_NEON_2003:
2015-10-10 13:01:25 -07:00
configureNeon2003TriggerShape(triggerShape PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
break;
case TT_FORD_ASPIRE:
configureFordAspireTriggerShape(triggerShape);
break;
case TT_GM_7X:
// todo: fix this configureGmTriggerShape(triggerShape);
configureFordAspireTriggerShape(triggerShape);
break;
case TT_MAZDA_DOHC_1_4:
2015-10-10 13:01:25 -07:00
configureMazdaProtegeLx(triggerShape PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
break;
case TT_ONE_PLUS_ONE:
configureOnePlusOne(triggerShape, engineConfiguration->operationMode);
break;
case TT_ONE_PLUS_TOOTHED_WHEEL_60_2:
configureOnePlus60_2(triggerShape, engineConfiguration->operationMode);
break;
case TT_ONE:
setToothedWheelConfiguration(triggerShape, 1, 0, engineConfiguration->operationMode);
break;
case TT_MAZDA_SOHC_4:
2015-10-10 13:01:25 -07:00
configureMazdaProtegeSOHC(triggerShape PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
break;
case TT_MINI_COOPER_R50:
configureMiniCooperTriggerShape(triggerShape);
break;
case TT_TOOTHED_WHEEL_60_2:
setToothedWheelConfiguration(triggerShape, 60, 2, engineConfiguration->operationMode);
break;
case TT_60_2_VW:
setVwConfiguration(triggerShape);
break;
case TT_TOOTHED_WHEEL_36_1:
setToothedWheelConfiguration(triggerShape, 36, 1, engineConfiguration->operationMode);
break;
case TT_HONDA_ACCORD_CD_TWO_WIRES:
configureHondaAccordCD(triggerShape, false, true, T_CHANNEL_3, T_PRIMARY, 0);
break;
case TT_HONDA_ACCORD_CD:
configureHondaAccordCD(triggerShape, true, true, T_CHANNEL_3, T_PRIMARY, 0);
break;
case TT_HONDA_ACCORD_1_24:
configureHondaAccordCD(triggerShape, true, false, T_PRIMARY, T_PRIMARY, 10);
break;
case TT_HONDA_ACCORD_CD_DIP:
configureHondaAccordCDDip(triggerShape);
break;
case TT_MITSU:
initializeMitsubishi4g18(triggerShape);
break;
case TT_DODGE_RAM:
2015-10-10 13:01:25 -07:00
initDodgeRam(triggerShape PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
break;
2015-09-10 19:01:35 -07:00
case TT_36_2_2_2:
initialize36_2_2_2(triggerShape);
break;
2015-12-14 18:01:30 -08:00
case TT_2JZ:
initialize2jzGE(triggerShape);
break;
2015-09-19 16:01:46 -07:00
case TT_NISSAN:
initializeNissan(triggerShape);
break;
2015-12-27 12:02:51 -08:00
case TT_ROVER_K:
initializeRoverK(triggerShape);
break;
2015-07-10 06:01:56 -07:00
default:
firmwareError("initializeTriggerShape() not implemented: %d", triggerConfig->type);
return;
}
wave.checkSwitchTimes(getSize());
2016-01-24 22:02:55 -08:00
/**
* this instance is used only to initialize 'this' TriggerShape instance
* #192 BUG real hardware trigger events could be coming even while we are initializing trigger
*/
state.reset();
calculateTriggerSynchPoint(&state PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
}
static void onFindIndex(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!
2015-09-08 20:01:07 -07:00
state->expectedTotalTime[i] = state->currentCycle.totalTimeNt[i];
2015-07-10 06:01:56 -07:00
}
}
/**
* Trigger shape is defined in a way which is convenient for trigger shape definition
* On the other hand, trigger decoder indexing begins from synchronization event.
*
* This function finds the index of synchronization event within TriggerShape
*/
2015-09-23 20:01:40 -07:00
uint32_t findTriggerZeroEventIndex(TriggerState *state, TriggerShape * shape,
trigger_config_s const*triggerConfig DECLARE_ENGINE_PARAMETER_S) {
2015-09-13 07:01:39 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-09-23 20:01:40 -07:00
efiAssert(getRemainingStack(chThdSelf()) > 128, "findPos", -1);
2015-09-13 07:01:39 -07:00
#endif
2015-07-10 06:01:56 -07:00
errorDetection.clear();
2015-09-13 13:01:38 -07:00
efiAssert(state != NULL, "NULL state", -1);
2015-07-10 06:01:56 -07:00
2015-09-13 13:01:38 -07:00
state->reset();
2015-09-13 07:01:39 -07:00
2015-07-10 06:01:56 -07:00
// todo: should this variable be declared 'static' to reduce stack usage?
TriggerStimulatorHelper helper;
2015-09-23 18:02:33 -07:00
uint32_t index = helper.doFindTrigger(shape, triggerConfig, state PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
if (index == EFI_ERROR_CODE) {
return index;
}
2015-09-13 13:01:38 -07:00
efiAssert(state->getTotalRevolutionCounter() == 1, "totalRevolutionCounter", EFI_ERROR_CODE);
2015-07-10 06:01:56 -07:00
/**
* Now that we have just located the synch point, we can simulate the whole cycle
* in order to calculate expected duty cycle
*
* todo: add a comment why are we doing '2 * shape->getSize()' here?
*/
2015-09-13 13:01:38 -07:00
state->cycleCallback = onFindIndex;
2015-07-10 06:01:56 -07:00
2015-09-23 20:01:40 -07:00
helper.assertSyncPositionAndSetDutyCycle(index, state, shape, triggerConfig PASS_ENGINE_PARAMETER);
2015-07-10 06:01:56 -07:00
return index % shape->getSize();
}
void initTriggerDecoderLogger(Logging *sharedLogger) {
logger = sharedLogger;
}
void initTriggerDecoder(void) {
2015-09-13 07:01:39 -07:00
#if (EFI_PROD_CODE || EFI_SIMULATOR) || defined(__DOXYGEN__)
2015-09-23 20:01:40 -07:00
outputPinRegisterExt2("trg_err", &triggerDecoderErrorPin, boardConfiguration->triggerErrorPin,
&boardConfiguration->triggerErrorPinMode);
2015-07-10 06:01:56 -07:00
#endif
}
#endif /* EFI_SHAFT_POSITION_INPUT */