FreeEMS  0.2.0-SNAPSHOT-285-g028e24c
Functions | Variables
MissingTeeth-Either-XminusY.c File Reference

Missing teeth, M-N, with or without cam sync, configured externally. More...

#include "../inc/defaultSecondaryRPMISR.c"
Include dependency graph for MissingTeeth-Either-XminusY.c:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void decoderInitPreliminary ()
void perDecoderReset ()
void PrimaryRPMISR (void)
 RPM ISRs, IC timer for engine position and RPM.

Variables

unsigned char NumberOfTwinMatchedPairs
unsigned long lastInterEventPeriod
match matches

Detailed Description

Missing teeth, M-N, with or without cam sync, configured externally.

This file is generic, and built as an include with multiple headers containing the parameters required to make it function.

Documentation on how this decoder was designed & written is available here:

http://forum.diyefi.org/viewtopic.php?f=56&t=1340

Definition in file MissingTeeth-Either-XminusY.c.

Function Documentation

void decoderInitPreliminary ( void  )
Todo:
TODO Perhaps use some of the space freed by shrinking all timing tables for this: /unsigned long wheelEventTimeStamps[numberOfWheelEvents]; // For logging wheel patterns as observed

Definition at line 60 of file MissingTeeth-Either-XminusY.c.

References TCTL4.

{
TCTL4 = 0x01; /* Capture on rising edge of T0 only, capture off for 1,2,3 */
}
void perDecoderReset ( void  )

Definition at line 65 of file MissingTeeth-Either-XminusY.c.

References NumberOfTwinMatchedPairs.

{
NumberOfTwinMatchedPairs = 0; // Var for one more opportunity to sync :-)
}
void PrimaryRPMISR ( void  )

RPM ISRs, IC timer for engine position and RPM.

There are multiple copies of this interrupt handler, each is linked with the rest of the code once such that if there are N decoder implementations and/or variants, then there are N loadable binaries produced after a full build.

For details on any specific decoder implementation, see the documentation for that specific file.

Definition at line 70 of file MissingTeeth-Either-XminusY.c.

References decoderSetting::accelerationInputEventTimeTolerance, ADCBuffers, angleOfSingleIteration, BackwardNarrow, BIT0, CALC_FUEL_IGN, Clocks, coreStatusA, Counters, KeyUserDebug::currentEvent, DEBUG_TURN_PIN_OFF, DEBUG_TURN_PIN_ON, decoderSetting::decelerationInputEventTimeTolerance, DECODER_BENCHMARKS, KeyUserDebug::decoderFlags, fixedConfig2::decoderSettings, edgeTimeStamp, eventAngles, fixedConfigs2, KeyUserDebug::inputEventTimeTolerance, KeyUserDebugs, LAST_MATCH_VALID, LAST_PERIOD_VALID, LAST_TIMESTAMP_VALID, LAST_TPD_VALID, lastEventTimeStamp, lastInterEventPeriod, twoPairs::lastPair, lastTicksPerDegree, MaskBySumPattern, MatchedPair, MatchedPairMatchedPair, MatchedPairNarrowWide, MISSING_TEETH, decoderSetting::missingToothTolerance, NarrowBackward, NarrowWide, NarrowWideWideNarrow, NBIT0, noiseAppearedWayTooEarlyAsIfItWasAVRToothButWasnt, NUMBER_OF_WHEEL_EVENTS, numberOfRealEvents, NumberOfTwinMatchedPairs, OK_TO_SCHEDULE, match::pairs, match::pattern, PORTB, PRIMARY_EVENT_ARRIVED_TOO_EARLY, PRIMARY_EVENT_ARRIVED_TOO_LATE, KeyUserDebug::primaryTeethSeen, PTIT, resetToNonRunningState(), sampleEachADC(), SET_SYNC_LEVEL_TO, Counter::syncedADCreadings, TC0, TFLG, TFLGOF, twoPairs::thisPair, ticks_per_degree_multiplier, ticksPerDegreeRecord, LongTime::timeLong, Clock::timeoutADCreadingClock, timerExtensionClock, LongTime::timeShorts, timeStamp, WideNarrow, WideNarrowMatchedPair, yourSyncToleranceIsLooserThanAWellYouGetTheIdea, yourSyncToleranceIsTighterThanAWellYouGetTheIdea, and yourVRSensorHasALoosePlugFixIt.

{
/* Clear the interrupt flag for this input compare channel */
TFLG = 0x01;
/* Save all relevant available data here */
unsigned short edgeTimeStamp = TC0; /* Save the edge time stamp */
unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */
/* Install the low word */
timeStamp.timeShorts[1] = edgeTimeStamp;
/* Find out what our timer value means and put it in the high word */
if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
timeStamp.timeShorts[0] = timerExtensionClock + 1;
}else{
}
unsigned long thisEventTimeStamp = timeStamp.timeLong;
if(PTITCurrentState & 0x01){
// Calc this period
unsigned char lastEvent = 0;
unsigned long thisInterEventPeriod = 0;
unsigned char initialOkToSchedule = KeyUserDebugs.decoderFlags & OK_TO_SCHEDULE;
thisInterEventPeriod = thisEventTimeStamp - lastEventTimeStamp;
if((KeyUserDebugs.decoderFlags & LAST_PERIOD_VALID) && !initialOkToSchedule){// If it's OK to schedule, skip this and get on with it!
unsigned long larger;
unsigned long smaller;
unsigned char thisLargerThanLast;
if(thisInterEventPeriod > lastInterEventPeriod){
larger = thisInterEventPeriod;
thisLargerThanLast = 1;
}else{
smaller = thisInterEventPeriod;
thisLargerThanLast = 0;
}
lastInterEventPeriod = thisInterEventPeriod;
// Calculate tolerance, then add and subtract it from whatever required
unsigned long tolerance = (smaller * MISSING_TEETH * fixedConfigs2.decoderSettings.missingToothTolerance) / 4096;
// div by 4k = fairly high minimum RPM for low teeth wheels
// perhaps provide some options for different tolerance on different types of expected widths
// the wide one on larger missing counts has more time to get to a higher RPM and needs a wider tolerance
// possible options: different percent of smaller for each type, different percent and based on ideal w/b instead of smaller
// Another option that keeps the 25% tolerance as the correct amount for any missing count is to simply take the percentage of
// the smaller component and multiply by the number of missing teeth! This can be a flash config flag option or possibly rpm thresholded
// it could be done on a per level basis too.
unsigned long idealWide = 0;
unsigned long idealBackward = 0;
if(larger < (smaller + tolerance)){ // has to be first to be most efficient
matches.pairs.thisPair = MatchedPair; // same period, roughly
}else{
idealWide = smaller * (MISSING_TEETH + 1); // has to be second to be most efficient
if((larger < (idealWide + tolerance)) && (larger > (idealWide - tolerance))){
if(thisLargerThanLast){
}else{
}
}else{ // We're not in good shape...
idealBackward = ((smaller * (MISSING_TEETH + 2)) / 2); // this leads to further code running later, so should come next
if((larger < (idealBackward + tolerance)) && (larger > (idealBackward - tolerance))){
if(thisLargerThanLast){
}else{
}
}else if(larger > (idealWide + tolerance)){ // We're in very bad shape...
if(thisLargerThanLast){
return;
}else{
return;
}
}else{ // Fell between the cracks, not matched, settings very tight, therefore was in two possible places on either side of (N+2)/2.
return;
}
}
}
// This all needs a little more complexity for cam only/crank only/crank + cam sync use, hard coded to crank only for now
if(KeyUserDebugs.decoderFlags & LAST_MATCH_VALID){ // If we have enough data
if(KeyUserDebugs.decoderFlags & CONFIGURED_SYNC){
}
if((KeyUserDebugs.currentEvent == 0) && (matches.pattern != MatchedPairNarrowWide)){ // First event after gap
return;
}else if((KeyUserDebugs.currentEvent == 1) && (matches.pattern != NarrowWideWideNarrow)){ // Second event after gap
return;
}else if((KeyUserDebugs.currentEvent == 2) && (matches.pattern != WideNarrowMatchedPair)){ // Third event after gap
return;
}else if((KeyUserDebugs.currentEvent > 2) && (matches.pattern != MatchedPairMatchedPair)){ // All other events should be preceeded by two matched pairs
return;
}else{ // Add a confirmation if necessary
SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
}
}else{
if(matches.pattern == MatchedPairMatchedPair){ // | small | small | small | - All periods match, could be anywhere, unless...
// Because this method REQUIRES 4 evenly spaced teeth to work, it's only available to 5-1 or greater wheels.
if((NUMBER_OF_WHEEL_EVENTS > 3) && (NumberOfTwinMatchedPairs == (NUMBER_OF_WHEEL_EVENTS - 3))){ // This can't find a match until it's on it's fourth execution
// This will match repeatedly then un-sync on next cycle if tolerance is set too high
lastEvent = KeyUserDebugs.currentEvent - 1;
SET_SYNC_LEVEL_TO(CONFIGURED_SYNC); // Probability of this = (N + 1) / M
// Sample RPM and ADCs here on the basis of cylinders and revolutions
// IE, sample RPM once (total teeth (inc missing) per engine cycle / cyls) events have passed
// And, do it from the last matching tooth, and do that on every tooth
// So have a buffer of time stamps, which would take a LOT of RAM, hmmm, perhaps just wait.
// Missing teeth users are clearly not fussed about fast starting anyway
// And once sync is gained good readings can be taken without excess memory usage
}else if((NUMBER_OF_WHEEL_EVENTS > 3) && (NumberOfTwinMatchedPairs > (NUMBER_OF_WHEEL_EVENTS - 3))){ // More matched pairs than possible with config
return;
} // else fall through to wait.
}else if(matches.pattern == MatchedPairNarrowWide){ // | small | small | BIG | Last tooth is first tooth after missing - ((M-N)-3)/M = common
lastEvent = NUMBER_OF_WHEEL_EVENTS - 1; // Zero indexed
SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
}else if(matches.pattern == NarrowWideWideNarrow){ // | small | BIG | small | Last tooth is second tooth after missing - 1/M
lastEvent = 0;
SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
}else if(matches.pattern == WideNarrowMatchedPair){ // | BIG | small | small | Last tooth is third tooth after missing - 1/M
lastEvent = 1;
SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
}else{
resetToNonRunningState(matches.pattern); // Where they are defined individually in the error file! Beautiful!!
return;
}
}
}
// Stash the pair description for next time
}
}
unsigned short thisTicksPerDegree = 0;
if(KeyUserDebugs.decoderFlags & CONFIGURED_SYNC){
if(initialOkToSchedule){ // Only do this if not done above
}
}
unsigned short thisAngle = 0;
thisAngle = eventAngles[KeyUserDebugs.currentEvent] + angleOfSingleIteration - eventAngles[lastEvent] ; // Optimisable... leave readable for now! :-p J/K learn from this...
}else{
}
thisTicksPerDegree = (unsigned short)((ticks_per_degree_multiplier * thisInterEventPeriod) / thisAngle); // with current scale range for 60/12000rpm is largest ticks per degree = 3472, smallest = 17 with largish error
unsigned short ratioBetweenThisAndLast = (unsigned short)(((unsigned long)lastTicksPerDegree * 1000) / thisTicksPerDegree);
KeyUserDebugs.inputEventTimeTolerance = ratioBetweenThisAndLast;
return;
return;
}
}
if(initialOkToSchedule){ // Skip one execution
SCHEDULE_ECT_OUTPUTS();
}
// sample adcs and record rpm here after scheduling
*ticksPerDegreeRecord = thisTicksPerDegree;
// Set flag to say calc required
// Reset the clock for reading timeout
}
OUTPUT_COARSE_BBS();
}else{
lastInterEventPeriod = thisInterEventPeriod;
}
lastTicksPerDegree = thisTicksPerDegree;
}
// Always
lastEventTimeStamp = thisEventTimeStamp;
}else{
// do checking for width variance too, perhaps optionally.
}
}

Here is the call graph for this function:

Variable Documentation

unsigned char NumberOfTwinMatchedPairs

Definition at line 55 of file MissingTeeth-Either-XminusY.c.

Referenced by perDecoderReset(), and PrimaryRPMISR().

unsigned long lastInterEventPeriod

Definition at line 56 of file MissingTeeth-Either-XminusY.c.

Referenced by PrimaryRPMISR().

match matches

Definition at line 57 of file MissingTeeth-Either-XminusY.c.