FreeEMS  0.2.0-SNAPSHOT-282-g9efc524
Functions

For evenly spaced teeth on the cam or crank with a single second input. More...

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 ()
 RPM ISRs, IC timer for engine position and RPM.
void SecondaryRPMISR ()
 RPM ISRs, IC timer for engine position and RPM.

Detailed Description

For evenly spaced teeth on the cam or crank with a single second input.

Fill out a data reverse header and include this file. Sync is provided by the second input allowing a sequential and/or COP/CNP setup to be used.

VR edition with only one edge used!

Definition in file EvenTeeth-Xand1.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 41 of file EvenTeeth-Xand1.c.

References TCTL4.

{
// Set PT0 and PT1 to only capture on rising
TCTL4 = 0x05; // 0000 0101 Capture rising edges only on PT0&1
}
void perDecoderReset ( void  )

Definition at line 46 of file EvenTeeth-Xand1.c.

{} // Nothing special to reset for this code
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 49 of file EvenTeeth-Xand1.c.

References decoderSetting::accelerationInputEventTimeTolerance, ADCBuffers, BIT0, CALC_FUEL_IGN, Clocks, coreStatusA, COUNT_OF_EVENTS_IMPOSSIBLY_HIGH_NOISE, 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_PERIOD_VALID, LAST_TIMESTAMP_VALID, lastPrimaryEventTimeStamp, lastPrimaryTicksPerDegree, NBIT0, numberOfRealEvents, PORTB, PRIMARY_EVENT_ARRIVED_TOO_EARLY, PRIMARY_EVENT_ARRIVED_TOO_LATE, KeyUserDebug::primaryTeethSeen, PTIT, resetToNonRunningState(), sampleEachADC(), Counter::syncedADCreadings, TC0, TFLG, TFLGOF, ticks_per_degree_multiplier, ticksPerDegreeRecord, LongTime::timeLong, Clock::timeoutADCreadingClock, timerExtensionClock, LongTime::timeShorts, and timeStamp.

{
/* 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 */
// Prevent main from clearing values before sync is obtained!
/* 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;
unsigned long thisInterEventPeriod = 0;
unsigned short thisTicksPerDegree = 0;
thisInterEventPeriod = thisEventTimeStamp - lastPrimaryEventTimeStamp;
thisTicksPerDegree = (unsigned short)((ticks_per_degree_multiplier * thisInterEventPeriod) / eventAngles[1]); // with current scale range for 60/12000rpm is largest ticks per degree = 3472, smallest = 17 with largish error
}
if(KeyUserDebugs.decoderFlags & CONFIGURED_SYNC){
return;
}// Can never be greater than without a code error or genuine noise issue, so give it a miss as we can not guarantee where we are now.
unsigned short ratioBetweenThisAndLast = (unsigned short)(((unsigned long)lastPrimaryTicksPerDegree * 1000) / thisTicksPerDegree);
KeyUserDebugs.inputEventTimeTolerance = ratioBetweenThisAndLast;
return;
return;
}else{
if(PTITCurrentState & 0x01){
// TODO Calculate RPM from last primaryLeadingEdgeTimeStamp
}else{
// TODO Calculate RPM from last primaryTrailingEdgeTimeStamp
}
}
}/*else*/ if(KeyUserDebugs.decoderFlags & LAST_TIMESTAMP_VALID){ // TODO temp for testing just do rpm this way, fill above out later.
*ticksPerDegreeRecord = thisTicksPerDegree;
// Set flag to say calc required
// Reset the clock for reading timeout
}
// for now, sample always and see what we get result wise...
// if((currentEvent % 6) == 0){
// sampleEachADC(ADCBuffers);
// Counters.syncedADCreadings++;
//
// // Set flag to say calc required
// coreStatusA |= CALC_FUEL_IGN;
//
// // Reset the clock for reading timeout
// Clocks.timeoutADCreadingClock = 0;
// }
SCHEDULE_ECT_OUTPUTS();
}
OUTPUT_COARSE_BBS();
// do these always at first, and use them with a single 30 degree angle for the first cut
lastPrimaryTicksPerDegree = thisTicksPerDegree;
}
// Always
lastPrimaryEventTimeStamp = thisEventTimeStamp;
}

Here is the call graph for this function:

void SecondaryRPMISR ( 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 146 of file EvenTeeth-Xand1.c.

{
/* Clear the interrupt flag for this input compare channel */
TFLG = 0x02;
/* Save all relevant available data here */
unsigned short edgeTimeStamp = TC1; /* Save the timestamp */
// 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;
unsigned long thisInterEventPeriod = 0;
thisInterEventPeriod = thisEventTimeStamp - lastSecondaryEventTimeStamp;
}
// This sets currentEvent to 255 such that when the primary ISR runs it is rolled over to zero!
if(KeyUserDebugs.decoderFlags & CONFIGURED_SYNC){
// If sync not confirmed, register sync point. Must be before the count checks, otherwise loss of sync would result in sync being redeclared.
SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
}
/* If the count is less than 23, then we know that the electrical pulse that triggered
* this ISR execution was almost certainly in error and it is NOT valid to stay in sync.
*
* If the count is greater than 24, then we know that an electrical noise pulse triggered
* the other interrupt in between and was missed by the time period checks (unlikely, but
* possible) and that, therefore, there could have been a noise pulse on this input too,
* and therefore we don't really know where we are.
*
* In the case where the count is exactly 24 we can only rely on the time period checks in
* the other ISR, which should be sufficient unless poorly setup by a user with too wide
* of a tolerance level.
*
* There is zero point adding relative timing checks to this ISR because by nature, the
* other N teeth have already checked out good timing wise and therefore the average also
* does. Thus if we did check, for it to ever fail it would need to be tighter, and in
* reality it must be more loose due to the larger possible variation over the much much
* larger time frame.
*/
} // ELSE do nothing, and be happy :-)
}else{ // If sync not found, register first sync point, as this is our reference point.
SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
}
KeyUserDebugs.currentEvent = 0xFF; // TODO reset always, and catch noise induced errors below, this behaviour (now some lines above) may be bad/not fussy enough, or could be good, depending upon determinate nature of the inter event timing between primary and secondary, or not, perhaps move "lose sync or correct sync" as a configuration variable
}