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