Change to single decoder state variable. Small (12 byte) RAM free up

This commit is contained in:
Josh Stewart 2022-11-22 15:53:35 +11:00
parent 86319f43ca
commit 4693cb2013
7 changed files with 192 additions and 153 deletions

View File

@ -7,6 +7,8 @@
#define CRANKMATH_METHOD_ALPHA_BETA 3
#define CRANKMATH_METHOD_2ND_DERIVATIVE 4
#define SECOND_DERIV_ENABLED 0
//#define fastDegreesToUS(targetDegrees) ((targetDegrees) * (unsigned long)timePerDegree)
#define fastDegreesToUS(targetDegrees) (((targetDegrees) * (unsigned long)timePerDegreex16) >> 4)
/*#define fastTimeToAngle(time) (((unsigned long)time * degreesPeruSx2048) / 2048) */ //Divide by 2048 will be converted at compile time to bitshift

View File

@ -37,7 +37,7 @@ unsigned long angleToTime(int16_t angle, byte method)
else if (method == CRANKMATH_METHOD_INTERVAL_TOOTH)
{
//Still uses a last interval method (ie retrospective), but bases the interval on the gap between the 2 most recent teeth rather than the last full revolution
if(triggerToothAngleIsCorrect == true)
if(BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT))
{
noInterrupts();
unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime);
@ -73,7 +73,7 @@ uint16_t timeToAngle(unsigned long time, byte method)
else if (method == CRANKMATH_METHOD_INTERVAL_TOOTH)
{
//Still uses a last interval method (ie retrospective), but bases the interval on the gap between the 2 most recent teeth rather than the last full revolution
if(triggerToothAngleIsCorrect == true)
if(BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT))
{
noInterrupts();
unsigned long toothTime = (toothLastToothTime - toothLastMinusOneToothTime);
@ -106,7 +106,7 @@ void doCrankSpeedCalcs(void)
//We use a 1st Deriv acceleration prediction, but only when there is an even spacing between primary sensor teeth
//Any decoder that has uneven spacing has its triggerToothAngle set to 0
//THIS IS CURRENTLY DISABLED FOR ALL DECODERS! It needs more work.
if( (secondDerivEnabled > 0) && (toothHistoryIndex >= 3) && (currentStatus.RPM < 2000) ) //toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm
if( SECOND_DERIV_ENABLED && (BIT_CHECK(decoderState, BIT_DECODER_2ND_DERIV)) && (toothHistoryIndex >= 3) && (currentStatus.RPM < 2000) ) //toothHistoryIndex must be greater than or equal to 3 as we need the last 3 entries. Currently this mode only runs below 3000 rpm
{
//Only recalculate deltaV if the tooth has changed since last time (DeltaV stays the same until the next tooth)
//if (deltaToothCount != toothCurrentCount)
@ -143,7 +143,7 @@ void doCrankSpeedCalcs(void)
{
//If we can, attempt to get the timePerDegree by comparing the times of the last two teeth seen. This is only possible for evenly spaced teeth
noInterrupts();
if( (triggerToothAngleIsCorrect == true) && (toothLastToothTime > toothLastMinusOneToothTime) && (abs(currentStatus.rpmDOT) > 30) )
if( (BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT)) && (toothLastToothTime > toothLastMinusOneToothTime) && (abs(currentStatus.rpmDOT) > 30) )
{
//noInterrupts();
unsigned long tempToothLastToothTime = toothLastToothTime;

View File

@ -36,6 +36,26 @@
#define DECODER_NGC 22
#define DECODER_VMAX 23
#define BIT_DECODER_2ND_DERIV 0 //The use of the 2nd derivative calculation is limited to certain decoders. This is set to either true or false in each decoders setup routine
#define BIT_DECODER_IS_SEQUENTIAL 1 //Whether or not the decoder supports sequential operation
#define BIT_DECODER_UNUSED1 2
#define BIT_DECODER_HAS_SECONDARY 3 //Whether or not the decoder supports fixed cranking timing
#define BIT_DECODER_HAS_FIXED_CRANKING 4
#define BIT_DECODER_VALID_TRIGGER 5 //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters)
#define BIT_DECODER_TOOTH_ANG_CORRECT 6 //Whether or not the triggerToothAngle variable is currently accurate. Some patterns have times when the triggerToothAngle variable cannot be accurately set.
//220 bytes free
extern volatile uint8_t decoderState;
/*
extern volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters)
extern volatile bool triggerToothAngleIsCorrect; //Whether or not the triggerToothAngle variable is currently accurate. Some patterns have times when the triggerToothAngle variable cannot be accurately set.
extern bool secondDerivEnabled; //The use of the 2nd derivative calculation is limited to certain decoders. This is set to either true or false in each decoders setup routine
extern bool decoderIsSequential; //Whether or not the decoder supports sequential operation
extern bool decoderHasSecondary; //Whether or not the pattern uses a secondary input
extern bool decoderHasFixedCrankingTiming;
*/
//This isn't to to filter out wrong pulses on triggers, but just to smooth out the cam angle reading for better closed loop VVT control.
#define ANGLE_FILTER(input, alpha, prior) (((long)input * (256 - alpha) + ((long)prior * alpha))) >> 8
@ -236,15 +256,8 @@ extern volatile unsigned long secondaryLastToothTime1; //The time (micros()) tha
extern uint16_t triggerActualTeeth;
extern volatile unsigned long triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering)
extern volatile unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input
extern volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters)
extern unsigned int triggerSecFilterTime_duration; // The shortest valid time (in uS) pulse DURATION
extern volatile uint16_t triggerToothAngle; //The number of crank degrees that elapse per tooth
extern volatile bool triggerToothAngleIsCorrect; //Whether or not the triggerToothAngle variable is currently accurate. Some patterns have times when the triggerToothAngle variable cannot be accurately set.
extern bool secondDerivEnabled; //The use of the 2nd derivative calculation is limited to certain decoders. This is set to either true or false in each decoders setup routine
extern bool decoderIsSequential; //Whether or not the decoder supports sequential operation
extern bool decoderIsLowRes; //Is set true, certain extra calculations are performed for better timing accuracy
extern bool decoderHasSecondary; //Whether or not the pattern uses a secondary input
extern bool decoderHasFixedCrankingTiming; //Whether or not the decoder supports fixed cranking timing
extern byte checkSyncToothCount; //How many teeth must've been seen on this revolution before we try to confirm sync (Useful for missing tooth type decoders)
extern unsigned long elapsedTime;
extern unsigned long lastCrankAngleCalc;

View File

@ -79,15 +79,11 @@ volatile unsigned long secondaryLastToothTime1 = 0; //The time (micros()) that t
uint16_t triggerActualTeeth;
volatile unsigned long triggerFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering)
volatile unsigned long triggerSecFilterTime; // The shortest time (in uS) that pulses will be accepted (Used for debounce filtering) for the secondary input
volatile bool validTrigger; //Is set true when the last trigger (Primary or secondary) was valid (ie passed filters)
volatile uint8_t decoderState = 0;
unsigned int triggerSecFilterTime_duration; // The shortest valid time (in uS) pulse DURATION
volatile uint16_t triggerToothAngle; //The number of crank degrees that elapse per tooth
volatile bool triggerToothAngleIsCorrect = false; //Whether or not the triggerToothAngle variable is currently accurate. Some patterns have times when the triggerToothAngle variable cannot be accurately set.
bool secondDerivEnabled = false; //The use of the 2nd derivative calculation is limited to certain decoders. This is set to either true or false in each decoders setup routine
bool decoderIsSequential; //Whether or not the decoder supports sequential operation
bool decoderIsLowRes = false; //Is set true, certain extra calculations are performed for better timing accuracy
bool decoderHasSecondary = false; //Whether or not the pattern uses a secondary input
bool decoderHasFixedCrankingTiming = false; //Whether or not the decoder supports fixed cranking timing
byte checkSyncToothCount; //How many teeth must've been seen on this revolution before we try to confirm sync (Useful for missing tooth type decoders)
unsigned long elapsedTime;
unsigned long lastCrankAngleCalc;
@ -164,7 +160,7 @@ static inline void addToothLogEntry(unsigned long toothTime, bool whichTooth)
*/
void loggerPrimaryISR(void)
{
validTrigger = false; //This value will be set to the return value of the decoder function, indicating whether or not this pulse passed the filters
BIT_CLEAR(decoderState, BIT_DECODER_VALID_TRIGGER); //This value will be set to the return value of the decoder function, indicating whether or not this pulse passed the filters
bool validEdge = false; //This is set true below if the edge
/*
Need to still call the standard decoder trigger.
@ -178,12 +174,11 @@ void loggerPrimaryISR(void)
triggerHandler();
validEdge = true;
}
if( (currentStatus.toothLogEnabled == true) && (validTrigger == true) )
if( (currentStatus.toothLogEnabled == true) && (BIT_CHECK(decoderState, BIT_DECODER_VALID_TRIGGER)) )
{
//Tooth logger only logs when the edge was correct
if(validEdge == true) { addToothLogEntry(curGap, TOOTH_CRANK); }
}
//else if( (currentStatus.compositeLogEnabled == true) && (validTrigger == true) )
else if( (currentStatus.compositeLogEnabled == true) )
{
//Composite logger adds an entry regardless of which edge it was
@ -196,8 +191,8 @@ void loggerPrimaryISR(void)
*/
void loggerSecondaryISR(void)
{
validTrigger = false; //This value will be set to the return value of the decoder function, indicating whether or not this pulse passed the filters
validTrigger = true;
BIT_CLEAR(decoderState, BIT_DECODER_VALID_TRIGGER); //This value will be set to the return value of the decoder function, indicating whether or not this pulse passed the filters
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //This value will be set to the return value of the decoder function, indicating whether or not this pulse passed the filters
/* 3 checks here:
1) If the primary trigger is RISING, then check whether the primary is currently HIGH
2) If the primary trigger is FALLING, then check whether the primary is currently LOW
@ -209,7 +204,7 @@ void loggerSecondaryISR(void)
triggerSecondaryHandler();
}
//No tooth logger for the secondary input
if( (currentStatus.compositeLogEnabled == true) && (validTrigger == true) )
if( (currentStatus.compositeLogEnabled == true) && (BIT_CHECK(decoderState, BIT_DECODER_VALID_TRIGGER)) )
{
//Composite logger adds an entry regardless of which edge it was
addToothLogEntry(curGap2, TOOTH_CAM);
@ -354,8 +349,14 @@ static inline void checkPerToothTiming(int16_t crankAngle, uint16_t currentTooth
*/
void triggerSetup_missingTooth(void)
{
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
triggerToothAngle = 360 / configPage4.triggerTeeth; //The number of degrees that passes from tooth to tooth
if(configPage4.TrigSpeed == CAM_SPEED) { triggerToothAngle = 720 / configPage4.triggerTeeth; } //Account for cam speed missing tooth
if(configPage4.TrigSpeed == CAM_SPEED)
{
//Account for cam speed missing tooth
triggerToothAngle = 720 / configPage4.triggerTeeth;
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
}
triggerActualTeeth = configPage4.triggerTeeth - configPage4.triggerMissingTeeth; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt
triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
if (configPage4.trigPatternSec == SEC_TRIGGER_4_1)
@ -366,8 +367,7 @@ void triggerSetup_missingTooth(void)
{
triggerSecFilterTime = (1000000 / (MAX_RPM / 60));
}
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
checkSyncToothCount = (configPage4.triggerTeeth) >> 1; //50% of the total teeth.
toothLastMinusOneToothTime = 0;
toothCurrentCount = 0;
@ -384,7 +384,7 @@ void triggerPri_missingTooth(void)
if ( curGap >= triggerFilterTime ) //Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS)
{
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
//if(toothCurrentCount > checkSyncToothCount || currentStatus.hasSync == false)
if( (toothLastToothTime > 0) && (toothLastMinusOneToothTime > 0) )
@ -456,7 +456,7 @@ void triggerPri_missingTooth(void)
triggerFilterTime = 0; //This is used to prevent a condition where serious intermittent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
triggerToothAngleIsCorrect = false; //The tooth angle is double at this point
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //The tooth angle is double at this point
}
}
}
@ -467,7 +467,7 @@ void triggerPri_missingTooth(void)
setFilter(curGap);
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
}
else
@ -702,9 +702,9 @@ void triggerSetup_DualWheel(void)
toothCurrentCount = 255; //Default value
triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
triggerSecFilterTime = (1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed)
secondDerivEnabled = false;
decoderIsSequential = true;
triggerToothAngleIsCorrect = true; //This is always true for this pattern
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //This is always true for this pattern
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
}
@ -718,7 +718,7 @@ void triggerPri_DualWheel(void)
if ( curGap >= triggerFilterTime )
{
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -922,11 +922,11 @@ void triggerSetup_BasicDistributor(void)
triggerFilterTime = 60000000L / MAX_RPM / configPage2.nCylinders; // Minimum time required between teeth
triggerFilterTime = triggerFilterTime / 2; //Safety margin
triggerFilterTime = 0;
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
toothCurrentCount = 0; //Default value
decoderHasFixedCrankingTiming = true;
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_HAS_FIXED_CRANKING);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
if(configPage2.nCylinders <= 4) { MAX_STALL_TIME = (1851UL * triggerToothAngle); }//Minimum 90rpm. (1851uS is the time per degree at 90rpm). This uses 90rpm rather than 50rpm due to the potentially very high stall time on a 4 cylinder if we wait that long.
else { MAX_STALL_TIME = (3200UL * triggerToothAngle); } //Minimum 50rpm. (3200uS is the time per degree at 50rpm).
@ -965,7 +965,7 @@ void triggerPri_BasicDistributor(void)
}
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
if ( configPage4.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) )
{
@ -1064,8 +1064,8 @@ void triggerSetEndTeeth_BasicDistributor(void)
void triggerSetup_GM7X(void)
{
triggerToothAngle = 360 / 6; //The number of degrees that passes from tooth to tooth
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
}
@ -1075,7 +1075,7 @@ void triggerPri_GM7X(void)
curTime = micros();
curGap = curTime - toothLastToothTime;
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
if( (toothLastToothTime > 0) && (toothLastMinusOneToothTime > 0) )
{
@ -1085,7 +1085,7 @@ void triggerPri_GM7X(void)
toothOneMinusOneTime = toothOneTime;
toothOneTime = curTime;
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
else
{
@ -1094,12 +1094,12 @@ void triggerPri_GM7X(void)
{
toothCurrentCount = 3;
currentStatus.hasSync = true;
triggerToothAngleIsCorrect = false;
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //The tooth angle is double at this point
currentStatus.startRevolutions++; //Counter
}
else
{
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
}
}
@ -1202,13 +1202,12 @@ void triggerSetup_4G63(void)
{
triggerToothAngle = 180; //The number of degrees that passes from tooth to tooth (primary)
toothCurrentCount = 99; //Fake tooth count represents no sync
secondDerivEnabled = false;
decoderIsSequential = true;
decoderHasFixedCrankingTiming = true;
triggerToothAngleIsCorrect = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
BIT_SET(decoderState, BIT_DECODER_HAS_FIXED_CRANKING);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
MAX_STALL_TIME = 366667UL; //Minimum 50rpm based on the 110 degree tooth spacing
if(initialisationComplete == false) { toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the initial check to prevent the fuel pump just staying on all the time
//decoderIsLowRes = true;
//Note that these angles are for every rising and falling edge
if(configPage2.nCylinders == 6)
@ -1258,7 +1257,7 @@ void triggerPri_4G63(void)
curGap = curTime - toothLastToothTime;
if ( (curGap >= triggerFilterTime) || (currentStatus.startRevolutions == 0) )
{
validTrigger = true; //Flag that this pulse was accepted as a valid trigger
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
triggerFilterTime = curGap >> 2; //This only applies during non-sync conditions. If there is sync then triggerFilterTime gets changed again below with a better value.
toothLastMinusOneToothTime = toothLastToothTime;
@ -1458,7 +1457,7 @@ void triggerSec_4G63(void)
if ( (curGap2 >= triggerSecFilterTime) )//|| (currentStatus.startRevolutions == 0) )
{
toothLastSecToothTime = curTime2;
validTrigger = true; //Flag that this pulse was accepted as a valid trigger
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
//addToothLogEntry(curGap, TOOTH_CAM);
triggerSecFilterTime = curGap2 >> 1; //Basic 50% filter for the secondary reading
@ -1666,9 +1665,9 @@ void triggerSetup_24X(void)
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
if(initialisationComplete == false) { toothCurrentCount = 25; toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the init check to prevent the fuel pump just staying on all the time
secondDerivEnabled = false;
decoderIsSequential = true;
triggerToothAngleIsCorrect = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
void triggerPri_24X(void)
@ -1695,7 +1694,7 @@ void triggerPri_24X(void)
triggerToothAngle = toothAngles[(toothCurrentCount-1)] - toothAngles[(toothCurrentCount-2)]; //Calculate the last tooth gap in degrees
}
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastToothTime = curTime;
@ -1778,9 +1777,9 @@ void triggerSetup_Jeep2000(void)
MAX_STALL_TIME = (3333UL * 60); //Minimum 50rpm. (3333uS is the time per degree at 50rpm). Largest gap between teeth is 60 degrees.
if(initialisationComplete == false) { toothCurrentCount = 13; toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the initial check to prevent the fuel pump just staying on all the time
secondDerivEnabled = false;
decoderIsSequential = false;
triggerToothAngleIsCorrect = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
void triggerPri_Jeep2000(void)
@ -1809,7 +1808,7 @@ void triggerPri_Jeep2000(void)
setFilter(curGap); //Recalc the new filter value
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -1874,9 +1873,9 @@ void triggerSetup_Audi135(void)
triggerFilterTime = (unsigned long)(1000000 / (MAX_RPM / 60 * 135UL)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
triggerSecFilterTime = (int)(1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed)
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
secondDerivEnabled = false;
decoderIsSequential = true;
triggerToothAngleIsCorrect = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
void triggerPri_Audi135(void)
@ -1894,7 +1893,7 @@ void triggerPri_Audi135(void)
{
//We only proceed for every third tooth
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothSystemLastToothTime = curTime;
toothSystemCount = 0;
toothCurrentCount++; //Increment the tooth counter
@ -1989,8 +1988,8 @@ void triggerSetup_HondaD17(void)
{
triggerToothAngle = 360 / 12; //The number of degrees that passes from tooth to tooth
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
}
void triggerPri_HondaD17(void)
@ -2000,7 +1999,7 @@ void triggerPri_HondaD17(void)
curGap = curTime - toothLastToothTime;
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
//
if( (toothCurrentCount == 13) && (currentStatus.hasSync == true) )
@ -2092,8 +2091,8 @@ void triggerSetup_Miata9905(void)
{
triggerToothAngle = 90; //The number of degrees that passes from tooth to tooth (primary)
toothCurrentCount = 99; //Fake tooth count represents no sync
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
triggerActualTeeth = 8;
if(initialisationComplete == false) { secondaryToothCount = 0; toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the initial check to prevent the fuel pump just staying on all the time
@ -2121,8 +2120,8 @@ void triggerSetup_Miata9905(void)
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
triggerFilterTime = 1500; //10000 rpm, assuming we're triggering on both edges off the crank tooth.
triggerSecFilterTime = 0; //Need to figure out something better for this
decoderHasFixedCrankingTiming = true;
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_HAS_FIXED_CRANKING);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
void triggerPri_Miata9905(void)
@ -2132,7 +2131,7 @@ void triggerPri_Miata9905(void)
if ( (curGap >= triggerFilterTime) || (currentStatus.startRevolutions == 0) )
{
toothCurrentCount++;
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
if( (toothCurrentCount == (triggerActualTeeth + 1)) )
{
toothCurrentCount = 1; //Reset the counter
@ -2364,8 +2363,8 @@ void triggerSetup_MazdaAU(void)
triggerToothAngle = 108; //The number of degrees that passes from tooth to tooth (primary). This is the maximum gap
toothCurrentCount = 99; //Fake tooth count represents no sync
secondaryToothCount = 0; //Needed for the cam tooth tracking
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
toothAngles[0] = 348; //tooth #1
toothAngles[1] = 96; //tooth #2
@ -2375,7 +2374,7 @@ void triggerSetup_MazdaAU(void)
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
triggerFilterTime = 1500; //10000 rpm, assuming we're triggering on both edges off the crank tooth.
triggerSecFilterTime = (int)(1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed)
decoderHasFixedCrankingTiming = true;
BIT_SET(decoderState, BIT_DECODER_HAS_FIXED_CRANKING);
}
void triggerPri_MazdaAU(void)
@ -2384,7 +2383,7 @@ void triggerPri_MazdaAU(void)
curGap = curTime - toothLastToothTime;
if ( curGap >= triggerFilterTime )
{
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothCurrentCount++;
if( (toothCurrentCount == 1) || (toothCurrentCount == 5) ) //Trigger is on CHANGE, hence 4 pulses = 1 crank rev
@ -2516,8 +2515,8 @@ void triggerSetup_non360(void)
toothCurrentCount = 255; //Default value
triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
triggerSecFilterTime = (1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed)
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
}
@ -2589,8 +2588,8 @@ void triggerSetup_Nissan360(void)
triggerFilterTime = (1000000 / (MAX_RPM / 60 * 360UL)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
triggerSecFilterTime = (int)(1000000 / (MAX_RPM / 60 * 2)) / 2; //Same as above, but fixed at 2 teeth on the secondary input and divided by 2 (for cam speed)
secondaryToothCount = 0; //Initially set to 0 prior to calculating the secondary window duration
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
toothCurrentCount = 1;
triggerToothAngle = 2;
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
@ -2603,7 +2602,7 @@ void triggerPri_Nissan360(void)
curGap = curTime - toothLastToothTime;
//if ( curGap < triggerFilterTime ) { return; }
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -2819,11 +2818,11 @@ void triggerSetup_Subaru67(void)
triggerFilterTime = (1000000 / (MAX_RPM / 60 * 360UL)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
triggerSecFilterTime = 0;
secondaryToothCount = 0; //Initially set to 0 prior to calculating the secondary window duration
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
toothCurrentCount = 1;
triggerToothAngle = 2;
triggerToothAngleIsCorrect = false;
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
toothSystemCount = 0;
MAX_STALL_TIME = (3333UL * 93); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
@ -2849,7 +2848,7 @@ void triggerPri_Subaru67(void)
//if ( curGap < triggerFilterTime ) { return; }
toothCurrentCount++; //Increment the tooth counter
toothSystemCount++; //Used to count the number of primary pulses that have occurred since the last secondary. Is part of the noise filtering system.
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -2888,7 +2887,7 @@ void triggerPri_Subaru67(void)
default:
//Almost certainly due to noise or cranking stop/start
currentStatus.hasSync = false;
triggerToothAngleIsCorrect = false;
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
currentStatus.syncLossCounter++;
secondaryToothCount = 0;
break;
@ -2918,7 +2917,7 @@ void triggerPri_Subaru67(void)
if(toothCurrentCount == 1) { triggerToothAngle = 55; } //Special case for tooth 1
else if(toothCurrentCount == 2) { triggerToothAngle = 93; } //Special case for tooth 2
else { triggerToothAngle = toothAngles[(toothCurrentCount-1)] - toothAngles[(toothCurrentCount-2)]; }
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
//NEW IGNITION MODE
@ -3072,8 +3071,8 @@ void triggerSetup_Daihatsu(void)
triggerToothAngle = 720 / triggerActualTeeth; //The number of degrees that passes from tooth to tooth
triggerFilterTime = 60000000L / MAX_RPM / configPage2.nCylinders; // Minimum time required between teeth
triggerFilterTime = triggerFilterTime / 2; //Safety margin
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
MAX_STALL_TIME = (1851UL * triggerToothAngle)*4;//Minimum 90rpm. (1851uS is the time per degree at 90rpm). This uses 90rpm rather than 50rpm due to the potentially very high stall time on a 4 cylinder if we wait that long.
@ -3103,7 +3102,7 @@ void triggerPri_Daihatsu(void)
//if ( curGap >= triggerFilterTime || (currentStatus.startRevolutions == 0 )
{
toothSystemCount++;
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
if (currentStatus.hasSync == true)
{
@ -3233,8 +3232,8 @@ Only rising Edge is used for simplicity.The second input is ignored, as it does
void triggerSetup_Harley(void)
{
triggerToothAngle = 0; // The number of degrees that passes from tooth to tooth, ev. 0. It alternates uneven
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
MAX_STALL_TIME = (3333UL * 60); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
if(initialisationComplete == false) { toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the initial check to prevent the fuel pump just staying on all the time
triggerFilterTime = 1500;
@ -3250,7 +3249,7 @@ void triggerPri_Harley(void)
{
if ( READ_PRI_TRIGGER() == HIGH) // Has to be the same as in main() trigger-attach, for readability we do it this way.
{
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
targetGap = lastGap ; //Gap is the Time to next toothtrigger, so we know where we are
toothCurrentCount++;
if (curGap > targetGap)
@ -3379,8 +3378,8 @@ void triggerSetup_ThirtySixMinus222(void)
triggerToothAngle = 10; //The number of degrees that passes from tooth to tooth
triggerActualTeeth = 30; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt
triggerFilterTime = (int)(1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
checkSyncToothCount = (configPage4.triggerTeeth) >> 1; //50% of the total teeth.
toothLastMinusOneToothTime = 0;
toothCurrentCount = 0;
@ -3396,7 +3395,7 @@ void triggerPri_ThirtySixMinus222(void)
if ( curGap >= triggerFilterTime ) //Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS)
{
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
//Begin the missing tooth detection
//If the time between the current tooth and the last is greater than 2x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after a gap
@ -3425,7 +3424,7 @@ void triggerPri_ThirtySixMinus222(void)
toothCurrentCount++;
toothCurrentCount++; //Accurately reflect the actual tooth count, including the skipped ones
}
triggerToothAngleIsCorrect = false; //The tooth angle is double at this point
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //The tooth angle is double at this point
triggerFilterTime = 0; //This is used to prevent a condition where serious intermittent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state
}
}
@ -3462,7 +3461,7 @@ void triggerPri_ThirtySixMinus222(void)
//Filter can only be recalculated for the regular teeth, not the missing one.
setFilter(curGap);
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
toothSystemCount = 0;
}
@ -3491,11 +3490,11 @@ uint16_t getRPM_ThirtySixMinus222(void)
if( currentStatus.RPM < currentStatus.crankRPM)
{
if( (configPage2.nCylinders == 4) && (toothCurrentCount != 19) && (toothCurrentCount != 16) && (toothCurrentCount != 34) && (triggerToothAngleIsCorrect == true) )
if( (configPage2.nCylinders == 4) && (toothCurrentCount != 19) && (toothCurrentCount != 16) && (toothCurrentCount != 34) && (BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT)) )
{
tempRPM = crankingGetRPM(36, 360);
}
else if( (configPage2.nCylinders == 6) && (toothCurrentCount != 9) && (toothCurrentCount != 12) && (toothCurrentCount != 33) && (triggerToothAngleIsCorrect == true) )
else if( (configPage2.nCylinders == 6) && (toothCurrentCount != 9) && (toothCurrentCount != 12) && (toothCurrentCount != 33) && (BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT)) )
{
tempRPM = crankingGetRPM(36, 360);
}
@ -3561,8 +3560,8 @@ void triggerSetup_ThirtySixMinus21(void)
triggerToothAngle = 10; //The number of degrees that passes from tooth to tooth
triggerActualTeeth = 33; //The number of physical teeth on the wheel. Doing this here saves us a calculation each time in the interrupt. Not Used
triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
checkSyncToothCount = (configPage4.triggerTeeth) >> 1; //50% of the total teeth.
toothLastMinusOneToothTime = 0;
toothCurrentCount = 0;
@ -3578,7 +3577,7 @@ void triggerPri_ThirtySixMinus21(void)
if ( curGap >= triggerFilterTime ) //Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS)
{
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
//Begin the missing tooth detection
//If the time between the current tooth and the last is greater than 2x the time between the last tooth and the tooth before that, we make the assertion that we must be at the first tooth after a gap
@ -3603,7 +3602,7 @@ void triggerPri_ThirtySixMinus21(void)
currentStatus.hasSync = true;
}
triggerToothAngleIsCorrect = false; //The tooth angle is double at this point
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //The tooth angle is double at this point
triggerFilterTime = 0; //This is used to prevent a condition where serious intermittent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state
}
}
@ -3623,7 +3622,7 @@ void triggerPri_ThirtySixMinus21(void)
//Filter can only be recalculated for the regular teeth, not the missing one.
setFilter(curGap);
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
@ -3651,7 +3650,7 @@ uint16_t getRPM_ThirtySixMinus21(void)
uint16_t tempRPM = 0;
if( currentStatus.RPM < currentStatus.crankRPM)
{
if( (toothCurrentCount != 20) && (triggerToothAngleIsCorrect == true) )
if( (toothCurrentCount != 20) && (BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT)) )
{
tempRPM = crankingGetRPM(36, 360);
}
@ -3694,11 +3693,11 @@ void triggerSetup_420a(void)
triggerFilterTime = (1000000 / (MAX_RPM / 60 * 360UL)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
triggerSecFilterTime = 0;
secondaryToothCount = 0; //Initially set to 0 prior to calculating the secondary window duration
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
toothCurrentCount = 1;
triggerToothAngle = 20; //Is only correct for the 4 short pulses before each TDC
triggerToothAngleIsCorrect = false;
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
toothSystemCount = 0;
MAX_STALL_TIME = (3333UL * 93); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
@ -3727,7 +3726,7 @@ void triggerPri_420a(void)
if ( curGap >= triggerFilterTime ) //Pulses should never be less than triggerFilterTime, so if they are it means a false trigger. (A 36-1 wheel at 8000pm will have triggers approx. every 200uS)
{
toothCurrentCount++; //Increment the tooth counter
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
if( (toothLastToothTime == 0) || (toothLastMinusOneToothTime == 0) ) { curGap = 0; }
@ -3744,7 +3743,7 @@ void triggerPri_420a(void)
//setFilter(curGap);
triggerFilterTime = 0;
triggerToothAngleIsCorrect = false;
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -3880,7 +3879,7 @@ void triggerPri_Webber(void)
toothCurrentCount++; //Increment the tooth counter
if (checkSyncToothCount > 0) { checkSyncToothCount++; }
if ( triggerSecFilterTime <= curGap ) { triggerSecFilterTime = curGap + (curGap>>1); } //150% crank tooth
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
toothLastMinusOneToothTime = toothLastToothTime;
toothLastToothTime = curTime;
@ -3992,8 +3991,8 @@ void triggerSetup_FordST170(void)
triggerSecFilterTime = 1000000 * 60 / MAX_RPM / 8 / 2; //Cam pattern is 8-3, so 2 nearest teeth are 90 deg crank angle apart. Cam can be advanced by 60 deg, so going from fully retarded to fully advanced closes the gap to 30 deg. Zetec cam pulleys aren't keyed from factory, so I subtracted additional 10 deg to avoid filter to be too aggressive. And there you have it 720/20=36.
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
checkSyncToothCount = (36) >> 1; //50% of the total teeth.
toothLastMinusOneToothTime = 0;
toothCurrentCount = 0;
@ -4145,9 +4144,9 @@ void triggerSetup_DRZ400(void)
toothCurrentCount = 255; //Default value
triggerFilterTime = (1000000 / (MAX_RPM / 60 * configPage4.triggerTeeth)); //Trigger filter time is the shortest possible time (in uS) that there can be between crank teeth (ie at max RPM). Any pulses that occur faster than this time will be discarded as noise
triggerSecFilterTime = (1000000 / (MAX_RPM / 60 * 2)); //Same as above, but fixed at 2 teeth on the secondary input
secondDerivEnabled = false;
decoderIsSequential = true;
triggerToothAngleIsCorrect = true; //This is always true for this pattern
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //This is always true for this pattern
MAX_STALL_TIME = (3333UL * triggerToothAngle); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
}
@ -4190,8 +4189,8 @@ The 6 and 8-cyl cam decoder uses the amount of teeth in the two previous groups
void triggerSetup_NGC(void)
{
secondDerivEnabled = false;
decoderIsSequential = true;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_SET(decoderState, BIT_DECODER_IS_SEQUENTIAL);
//Primary trigger
configPage4.triggerTeeth = 36; //The number of teeth on the wheel incl missing teeth.
@ -4254,7 +4253,7 @@ void triggerPri_NGC(void)
if ( curGap >= triggerFilterTime ) //Pulses should never be less than triggerFilterTime, so if they are it means a false trigger.
{
toothCurrentCount++;
validTrigger = true;
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
bool isMissingTooth = false;
if ( toothLastToothTime > 0 && toothLastMinusOneToothTime > 0 ) { //Make sure we haven't enough tooth information to calculate missing tooth length
@ -4266,7 +4265,7 @@ void triggerPri_NGC(void)
{
isMissingTooth = true; //Missing tooth detected
triggerFilterTime = 0; //This is used to prevent a condition where serious intermittent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state
triggerToothAngleIsCorrect = false; //The tooth angle is bigger at this point
BIT_CLEAR(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT); //The tooth angle is double at this point
// Figure out the polarity of the missing tooth by comparing how far ago the last tooth rose
if ((toothLastToothRisingTime - toothLastToothTime) < (curTime - toothLastToothRisingTime)) {
@ -4328,7 +4327,7 @@ void triggerPri_NGC(void)
{
//Regular (non-missing) tooth
setFilter(curGap);
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
}
}
@ -4467,7 +4466,7 @@ uint16_t getRPM_NGC(void)
uint16_t tempRPM = 0;
if( currentStatus.RPM < currentStatus.crankRPM)
{
if (triggerToothAngleIsCorrect == true) { tempRPM = crankingGetRPM(36, 360); }
if (BIT_CHECK(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT)) { tempRPM = crankingGetRPM(36, 360); }
else { tempRPM = currentStatus.RPM; } //Can't do per tooth RPM if we're at any of the missing teeth as it messes the calculation
}
else
@ -4578,12 +4577,12 @@ Trigger is based on 'CHANGE' so we get a signal on the up and downward edges of
void triggerSetup_Vmax(void)
{
triggerToothAngle = 0; // The number of degrees that passes from tooth to tooth, ev. 0. It alternates uneven
secondDerivEnabled = false;
decoderIsSequential = false;
BIT_CLEAR(decoderState, BIT_DECODER_2ND_DERIV);
BIT_CLEAR(decoderState, BIT_DECODER_IS_SEQUENTIAL);
MAX_STALL_TIME = (3333UL * 60); //Minimum 50rpm. (3333uS is the time per degree at 50rpm)
if(initialisationComplete == false) { toothLastToothTime = micros(); } //Set a startup value here to avoid filter errors when starting. This MUST have the initi check to prevent the fuel pump just staying on all the time
triggerFilterTime = 1500;
validTrigger = true; // We must start with a valid trigger or we cannot start measuring the lobe width. We only have a false trigger on the lobe up event when it doesn't pass the filter. Then, the lobe width will also not be beasured.
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); // We must start with a valid trigger or we cannot start measuring the lobe width. We only have a false trigger on the lobe up event when it doesn't pass the filter. Then, the lobe width will also not be beasured.
toothAngles[1] = 0; //tooth #1, these are the absolute tooth positions
toothAngles[2] = 40; //tooth #2
toothAngles[3] = 110; //tooth #3
@ -4606,10 +4605,10 @@ void triggerPri_Vmax(void)
curGap2 = curTime;
curGap = curTime - toothLastToothTime;
if ( (curGap >= triggerFilterTime) ){
validTrigger = true;
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
if (toothCurrentCount > 0) // We have sync based on the tooth width.
{
validTrigger = true; //Flag this pulse as being a valid trigger (ie that it passed filters)
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being a valid trigger (ie that it passed filters)
if (toothCurrentCount==1)
{
secondaryToothCount = 1;
@ -4662,10 +4661,11 @@ void triggerPri_Vmax(void)
}
}
else{
validTrigger = false;
BIT_CLEAR(decoderState, BIT_DECODER_VALID_TRIGGER); //Flag this pulse as being an invalid trigger
}
}
else if (validTrigger == true){// Inverted due to vr conditioner. So this is the falling lobe. We only process if there was a valid trigger.
else if( BIT_CHECK(decoderState, BIT_DECODER_VALID_TRIGGER) ) // Inverted due to vr conditioner. So this is the falling lobe. We only process if there was a valid trigger.
{
curGap3 = curTime - curGap2;
if (curGap3 > (lastGap * 2)){// Small lobe is 5 degrees, big lobe is 45 degrees. So this should be the wide lobe.
if (toothCurrentCount == 0 || toothCurrentCount == 6){//Wide should be seen with toothCurrentCount = 0, when there is no sync yet, or toothCurrentCount = 6 when we have done a full revolution.
@ -4686,8 +4686,9 @@ void triggerPri_Vmax(void)
lastGap = curGap3;
return;
}
else if (validTrigger == false){
validTrigger = true;//We reset this every time to ensure we only filter when needed.
else if( BIT_CHECK(decoderState, BIT_DECODER_VALID_TRIGGER) == false)
{
BIT_SET(decoderState, BIT_DECODER_VALID_TRIGGER); //We reset this every time to ensure we only filter when needed.
}
}

View File

@ -585,6 +585,13 @@ void initialiseAll(void)
currentStatus.nSquirts = 1;
req_fuel_uS = req_fuel_uS * 2;
}
else
{
//Should never happen, but default values
channel1InjDegrees = 0;
channel2InjDegrees = 120;
channel3InjDegrees = 240;
}
channel1InjEnabled = true;
channel2InjEnabled = true;
@ -606,7 +613,7 @@ void initialiseAll(void)
CRANK_ANGLE_MAX_IGN = 720;
maxIgnOutputs = 4;
}
else if(configPage4.sparkMode == IGN_MODE_ROTARY)
if(configPage4.sparkMode == IGN_MODE_ROTARY)
{
//Rotary uses the ign 3 and 4 schedules for the trailing spark. They are offset from the ign 1 and 2 channels respectively and so use the same degrees as them
channel3IgnDegrees = 0;
@ -640,6 +647,7 @@ void initialiseAll(void)
//Adjust the injection angles based on the number of squirts
channel2InjDegrees = (channel2InjDegrees * 2) / currentStatus.nSquirts;
}
else { } //Do nothing, default values are correct
}
else if (configPage2.injLayout == INJ_SEQUENTIAL)
{
@ -654,6 +662,16 @@ void initialiseAll(void)
currentStatus.nSquirts = 1;
req_fuel_uS = req_fuel_uS * 2;
}
else
{
//Should never happen, but default values
channel3InjEnabled = false;
channel4InjEnabled = false;
channel5InjEnabled = false;
channel6InjEnabled = false;
channel7InjEnabled = false;
channel8InjEnabled = false;
}
//Check if injector staging is enabled
if(configPage10.stagingEnabled == true)
@ -1182,6 +1200,7 @@ void initialiseAll(void)
ign4StartFunction = beginCoil4Charge;
ign4EndFunction = endCoil4Charge;
}
else { } //No action for other RX ignition modes (Future expansion / MISRA compliant).
break;
default:
@ -2983,7 +3002,11 @@ void initialiseTriggers(void)
triggerHandler = triggerPri_missingTooth;
triggerSecondaryHandler = triggerSec_missingTooth;
triggerTertiaryHandler = triggerThird_missingTooth;
decoderHasSecondary = true;
if( (configPage4.TrigSpeed == CRANK_SPEED) && ( (configPage4.sparkMode == IGN_MODE_SEQUENTIAL) || (configPage2.injLayout == INJ_SEQUENTIAL) ) )
{
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
}
getRPM = getRPM_missingTooth;
getCrankAngle = getCrankAngle_missingTooth;
triggerSetEndTeeth = triggerSetEndTeeth_missingTooth;
@ -3025,7 +3048,7 @@ void initialiseTriggers(void)
triggerSetup_DualWheel();
triggerHandler = triggerPri_DualWheel;
triggerSecondaryHandler = triggerSec_DualWheel;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_DualWheel;
getCrankAngle = getCrankAngle_DualWheel;
triggerSetEndTeeth = triggerSetEndTeeth_DualWheel;
@ -3059,7 +3082,7 @@ void initialiseTriggers(void)
triggerSetup_4G63();
triggerHandler = triggerPri_4G63;
triggerSecondaryHandler = triggerSec_4G63;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_4G63;
getCrankAngle = getCrankAngle_4G63;
triggerSetEndTeeth = triggerSetEndTeeth_4G63;
@ -3075,7 +3098,7 @@ void initialiseTriggers(void)
triggerSetup_24X();
triggerHandler = triggerPri_24X;
triggerSecondaryHandler = triggerSec_24X;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_24X;
getCrankAngle = getCrankAngle_24X;
triggerSetEndTeeth = triggerSetEndTeeth_24X;
@ -3092,7 +3115,7 @@ void initialiseTriggers(void)
triggerSetup_Jeep2000();
triggerHandler = triggerPri_Jeep2000;
triggerSecondaryHandler = triggerSec_Jeep2000;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_Jeep2000;
getCrankAngle = getCrankAngle_Jeep2000;
triggerSetEndTeeth = triggerSetEndTeeth_Jeep2000;
@ -3109,7 +3132,7 @@ void initialiseTriggers(void)
triggerSetup_Audi135();
triggerHandler = triggerPri_Audi135;
triggerSecondaryHandler = triggerSec_Audi135;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_Audi135;
getCrankAngle = getCrankAngle_Audi135;
triggerSetEndTeeth = triggerSetEndTeeth_Audi135;
@ -3126,7 +3149,7 @@ void initialiseTriggers(void)
triggerSetup_HondaD17();
triggerHandler = triggerPri_HondaD17;
triggerSecondaryHandler = triggerSec_HondaD17;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_HondaD17;
getCrankAngle = getCrankAngle_HondaD17;
triggerSetEndTeeth = triggerSetEndTeeth_HondaD17;
@ -3143,7 +3166,7 @@ void initialiseTriggers(void)
triggerSetup_Miata9905();
triggerHandler = triggerPri_Miata9905;
triggerSecondaryHandler = triggerSec_Miata9905;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_Miata9905;
getCrankAngle = getCrankAngle_Miata9905;
triggerSetEndTeeth = triggerSetEndTeeth_Miata9905;
@ -3162,7 +3185,7 @@ void initialiseTriggers(void)
triggerSetup_MazdaAU();
triggerHandler = triggerPri_MazdaAU;
triggerSecondaryHandler = triggerSec_MazdaAU;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_MazdaAU;
getCrankAngle = getCrankAngle_MazdaAU;
triggerSetEndTeeth = triggerSetEndTeeth_MazdaAU;
@ -3179,7 +3202,7 @@ void initialiseTriggers(void)
triggerSetup_non360();
triggerHandler = triggerPri_DualWheel; //Is identical to the dual wheel decoder, so that is used. Same goes for the secondary below
triggerSecondaryHandler = triggerSec_DualWheel; //Note the use of the Dual Wheel trigger function here. No point in having the same code in twice.
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_non360;
getCrankAngle = getCrankAngle_non360;
triggerSetEndTeeth = triggerSetEndTeeth_non360;
@ -3196,7 +3219,7 @@ void initialiseTriggers(void)
triggerSetup_Nissan360();
triggerHandler = triggerPri_Nissan360;
triggerSecondaryHandler = triggerSec_Nissan360;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_Nissan360;
getCrankAngle = getCrankAngle_Nissan360;
triggerSetEndTeeth = triggerSetEndTeeth_Nissan360;
@ -3213,7 +3236,7 @@ void initialiseTriggers(void)
triggerSetup_Subaru67();
triggerHandler = triggerPri_Subaru67;
triggerSecondaryHandler = triggerSec_Subaru67;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_Subaru67;
getCrankAngle = getCrankAngle_Subaru67;
triggerSetEndTeeth = triggerSetEndTeeth_Subaru67;
@ -3257,7 +3280,7 @@ void initialiseTriggers(void)
triggerSetup_ThirtySixMinus222();
triggerHandler = triggerPri_ThirtySixMinus222;
triggerSecondaryHandler = triggerSec_ThirtySixMinus222;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_ThirtySixMinus222;
getCrankAngle = getCrankAngle_missingTooth; //This uses the same function as the missing tooth decoder, so no need to duplicate code
triggerSetEndTeeth = triggerSetEndTeeth_ThirtySixMinus222;
@ -3280,7 +3303,7 @@ void initialiseTriggers(void)
triggerSetup_420a();
triggerHandler = triggerPri_420a;
triggerSecondaryHandler = triggerSec_420a;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_420a;
getCrankAngle = getCrankAngle_420a;
triggerSetEndTeeth = triggerSetEndTeeth_420a;
@ -3298,7 +3321,7 @@ void initialiseTriggers(void)
triggerSetup_DualWheel();
triggerHandler = triggerPri_Webber;
triggerSecondaryHandler = triggerSec_Webber;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_DualWheel;
getCrankAngle = getCrankAngle_DualWheel;
triggerSetEndTeeth = triggerSetEndTeeth_DualWheel;
@ -3317,7 +3340,7 @@ void initialiseTriggers(void)
triggerSetup_FordST170();
triggerHandler = triggerPri_missingTooth;
triggerSecondaryHandler = triggerSec_FordST170;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_FordST170;
getCrankAngle = getCrankAngle_FordST170;
triggerSetEndTeeth = triggerSetEndTeeth_FordST170;
@ -3336,7 +3359,7 @@ void initialiseTriggers(void)
triggerSetup_DRZ400();
triggerHandler = triggerPri_DualWheel;
triggerSecondaryHandler = triggerSec_DRZ400;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_DualWheel;
getCrankAngle = getCrankAngle_DualWheel;
triggerSetEndTeeth = triggerSetEndTeeth_DualWheel;
@ -3354,7 +3377,7 @@ void initialiseTriggers(void)
//Chrysler NGC - 4, 6 and 8 cylinder
triggerSetup_NGC();
triggerHandler = triggerPri_NGC;
decoderHasSecondary = true;
BIT_SET(decoderState, BIT_DECODER_HAS_SECONDARY);
getRPM = getRPM_NGC;
getCrankAngle = getCrankAngle_missingTooth;
triggerSetEndTeeth = triggerSetEndTeeth_NGC;

View File

@ -1049,7 +1049,7 @@ void loop(void)
//Same as above, except for ignition
//fixedCrankingOverride is used to extend the dwell during cranking so that the decoder can trigger the spark upon seeing a certain tooth. Currently only available on the basic distributor and 4g63 decoders.
if ( configPage4.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) && (decoderHasFixedCrankingTiming == true) )
if ( configPage4.ignCranklock && BIT_CHECK(currentStatus.engine, BIT_ENGINE_CRANK) && (BIT_CHECK(decoderState, BIT_DECODER_HAS_FIXED_CRANKING)) )
{
fixedCrankingOverride = currentStatus.dwell * 3;
//This is a safety step to prevent the ignition start time occurring AFTER the target tooth pulse has already occurred. It simply moves the start time forward a little, which is compensated for by the increase in the dwell time

View File

@ -75,7 +75,7 @@ void testCrankMaths()
{ .rpm = 20000, .triggerToothAngle = 180, .toothTime = 1500, .angle = 720, .expected = 6000 },
};
// The same for all tests
triggerToothAngleIsCorrect = true;
BIT_SET(decoderState, BIT_DECODER_TOOTH_ANG_CORRECT);
toothLastMinusOneToothTime = 200000;
for (auto testdata : crankmaths_tooth_testdatas) {