diff --git a/speeduino/board_stm32_official.h b/speeduino/board_stm32_official.h index 18dbf61b..c5e38211 100644 --- a/speeduino/board_stm32_official.h +++ b/speeduino/board_stm32_official.h @@ -200,6 +200,7 @@ HardwareTimer Timer11(TIM7); #endif #endif +#if ((STM32_CORE_VERSION_MINOR<=8) & (STM32_CORE_VERSION_MAJOR==1)) void oneMSInterval(HardwareTimer*); void boostInterrupt(HardwareTimer*); void fuelSchedule1Interrupt(HardwareTimer*); @@ -236,6 +237,7 @@ void ignitionSchedule7Interrupt(HardwareTimer*); #if (IGN_CHANNELS >= 8) void ignitionSchedule8Interrupt(HardwareTimer*); #endif +#endif //End core<=1.8 /* *********************************************************************************************************** diff --git a/speeduino/board_stm32_official.ino b/speeduino/board_stm32_official.ino index dc9fcdd5..637a3467 100644 --- a/speeduino/board_stm32_official.ino +++ b/speeduino/board_stm32_official.ino @@ -162,6 +162,7 @@ *********************************************************************************************************** * Interrupt callback functions */ + #if ((STM32_CORE_VERSION_MINOR<=8) & (STM32_CORE_VERSION_MAJOR==1)) void oneMSInterval(HardwareTimer*){oneMSInterval();} void boostInterrupt(HardwareTimer*){boostInterrupt();} void fuelSchedule1Interrupt(HardwareTimer*){fuelSchedule1Interrupt();} @@ -198,5 +199,5 @@ #if (IGN_CHANNELS >= 8) void ignitionSchedule8Interrupt(HardwareTimer*){ignitionSchedule8Interrupt();} #endif - + #endif //End core<=1.8 #endif diff --git a/speeduino/decoders.h b/speeduino/decoders.h index 139d5889..edf87ce0 100644 --- a/speeduino/decoders.h +++ b/speeduino/decoders.h @@ -140,6 +140,13 @@ uint16_t getRPM_ThirtySixMinus222(); int getCrankAngle_ThirtySixMinus222(); void triggerSetEndTeeth_ThirtySixMinus222(); +void triggerSetup_ThirtySixMinus21(); +void triggerPri_ThirtySixMinus21(); +void triggerSec_ThirtySixMinus21(); +uint16_t getRPM_ThirtySixMinus21(); +int getCrankAngle_ThirtySixMinus21(); +void triggerSetEndTeeth_ThirtySixMinus21(); + extern void (*triggerHandler)(); //Pointer for the trigger function (Gets pointed to the relevant decoder) extern void (*triggerSecondaryHandler)(); //Pointer for the secondary trigger function (Gets pointed to the relevant decoder) extern uint16_t (*getRPM)(); //Pointer to the getRPM function (Gets pointed to the relevant decoder) diff --git a/speeduino/decoders.ino b/speeduino/decoders.ino index 727eedc8..44f0bad7 100644 --- a/speeduino/decoders.ino +++ b/speeduino/decoders.ino @@ -3396,3 +3396,132 @@ void triggerSetEndTeeth_ThirtySixMinus222() lastToothCalcAdvance = currentStatus.advance; } + + +//************************************************************************************************************************ + +/* +Name: 36-2-1, For the 4B11 +Desc: A crank based trigger with a nominal 36 teeth, but with 1 single and 1 double missing tooth. +*/ +void triggerSetup_ThirtySixMinus21() +{ + 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 = (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 disgarded as noise + secondDerivEnabled = false; + decoderIsSequential = false; + checkSyncToothCount = (configPage4.triggerTeeth) >> 1; //50% of the total teeth. + toothLastMinusOneToothTime = 0; + toothCurrentCount = 0; + toothOneTime = 0; + toothOneMinusOneTime = 0; + MAX_STALL_TIME = (3333UL * triggerToothAngle * 2 ); //Minimum 50rpm. (3333uS is the time per degree at 50rpm) +} + +void triggerPri_ThirtySixMinus21() +{ + curTime = micros(); + curGap = curTime - toothLastToothTime; + 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) + + //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 + + targetGap2 = (3 * (toothLastToothTime - toothLastMinusOneToothTime)) ; //Multiply by 3 (Checks for a gap 3x greater than the last one) + targetGap = targetGap2 >> 1; //Multiply by 1.5 (Checks for a gap 1.5x greater than the last one) (Uses bitshift to divide by 2 as in the missing tooth deocder) + + if( (toothLastToothTime == 0) || (toothLastMinusOneToothTime == 0) ) { curGap = 0; } + + if ( (curGap > targetGap) ) + { + if ( (curGap < targetGap2)) + { + //we are at the tooth after the single gap + toothCurrentCount = 20; //it's either 19 or 20, need to clarify engine direction! + currentStatus.hasSync = true; + } + else + { + //we are at the tooth after the double gap + toothCurrentCount = 1; + currentStatus.hasSync = true; + } + + triggerToothAngleIsCorrect = false; //The tooth angle is double at this point + triggerFilterTime = 0; //This is used to prevent a condition where serious intermitent signals (Eg someone furiously plugging the sensor wire in and out) can leave the filter in an unrecoverable state + } + } + else + { + if( (toothCurrentCount > 36) || ( toothCurrentCount==1) ) + { + //Means a complete rotation has occured. + toothCurrentCount = 1; + revolutionOne = !revolutionOne; //Flip sequential revolution tracker + toothOneMinusOneTime = toothOneTime; + toothOneTime = curTime; + currentStatus.startRevolutions++; //Counter + + } + + //Filter can only be recalc'd for the regular teeth, not the missing one. + setFilter(curGap); + + triggerToothAngleIsCorrect = true; + + } + + toothLastMinusOneToothTime = toothLastToothTime; + toothLastToothTime = curTime; + + //EXPERIMENTAL! + if(configPage2.perToothIgn == true) + { + uint16_t crankAngle = ( (toothCurrentCount-1) * triggerToothAngle ) + configPage4.triggerAngle; + checkPerToothTiming(crankAngle, toothCurrentCount); + } + + +} + +void triggerSec_ThirtySixMinus21() +{ + //NOT USED - This pattern uses the missing tooth version of this function +} + +uint16_t getRPM_ThirtySixMinus21() +{ + uint16_t tempRPM = 0; + if( currentStatus.RPM < currentStatus.crankRPM) + { + if( (toothCurrentCount != 20) && (triggerToothAngleIsCorrect == true) ) + { + tempRPM = crankingGetRPM(36); + } + else { tempRPM = currentStatus.RPM; } //Can't do per tooth RPM if we're at tooth #1 as the missing tooth messes the calculation + } + else + { + tempRPM = stdGetRPM(360); + } + return tempRPM; +} + +int getCrankAngle_ThirtySixMinus21() +{ + //NOT USED - This pattern uses the missing tooth version of this function + return 0; +} + +void triggerSetEndTeeth_ThirtySixMinus21() +{ + ignition1EndTooth = 10; + ignition2EndTooth = 28; // Arbritrarilly picked at 180°. + + + lastToothCalcAdvance = currentStatus.advance; +}