FreeEMS  0.2.0-SNAPSHOT-285-g028e24c
Macros | Functions | Variables
GM-LT1-CAS-360and8.c File Reference

LT1 Optispark. More...

#include "../inc/freeEMS.h"
#include "../inc/interrupts.h"
#include "inc/GM-LT1-CAS-360and8.h"
#include "../inc/decoderInterface.h"
#include "../inc/utils.h"
#include "inc/defaultSecondaryRPMISR.c"
Include dependency graph for GM-LT1-CAS-360and8.c:

Go to the source code of this file.


#define LT1_360_8_C
#define windowsPerAllowedCumulativeBastardTooth   8


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


const unsigned short eventAngles []
const unsigned char eventValidForCrankSync [] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
const unsigned char windowCounts [] = {4,86,44,46,4,86,14,76,4,86,24,66,4,86,34,56}
unsigned char lastAccumulatorCount = 0xFF
unsigned char lastPARegisterReading = 0xFF
unsigned char windowState = 0
unsigned char lastNumberOfRealEvents = 0
unsigned char accumulatorRegisterCount = 0
signed char cumulativeBastardTeeth = 0
unsigned short cumulativeBastardTeethEroderCounter = 0

Detailed Description

LT1 Optispark.

Uses PT1 to interrupt on rising and falling events of the 8x cam sensor track. A certain number of 360x teeth will pass while PT1 is in a high or low state. Using that uniquek count we can set the positing of your Virtual CAS clock. After VCAS's position is set set PT7 to only interrupt on every 5th tooth, lowering the amount of interrupts generated, to a reasonable level.

Pseudo code that does not compile with zero warnings and errors MUST be commented out.
TODO config pulse accumulator to fire its own RPM interrupt to give the wheel more resoloution. Such as fire on every 10x.
Sean Keys

Definition in file GM-LT1-CAS-360and8.c.

Macro Definition Documentation


Definition at line 47 of file GM-LT1-CAS-360and8.c.

#define LT1_360_8_C

Definition at line 48 of file GM-LT1-CAS-360and8.c.

#define windowsPerAllowedCumulativeBastardTooth   8

Definition at line 83 of file GM-LT1-CAS-360and8.c.

Referenced by PrimaryRPMISR().

Function Documentation

void decoderInitPreliminary ( void  )
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 89 of file GM-LT1-CAS-360and8.c.

References ICPAR, PACN1, and TCTL4.

/* set pt1 to capture on rising and falling */
// set PACMX to 0 which is the default so there should be no need
// set to capture on rising and falling this way if we have an odd number in the PA we know something went wrong
// disable interrupt on PT1
ICPAR = 0x02; // set the second bit in ICPAR (PAC1) to enable PT1's pulse accumulator
// enable interrupt on overflow and set count to 0xFF-245 to enable an interrupt on every ten teeth
PACN1 = 0x00; // reset our count register
TCTL4 = 0xFF; /* Capture on both edges of pin 0 and only on the falling edges of pin 1, capture off for 2,3 */ // FRED why interrupt on the other one at all, there is no code and you're *causing* jitter in your primary rpm by doing this, along with eating CPU up.
//TIE = 0x01; // FRED necessary to do this too? I think so, but check the docs.
void perDecoderReset ( void  )
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 115 of file GM-LT1-CAS-360and8.c.

References accumulatorRegisterCount, ADCBuffers, AMBIGUOUS_COUNT, ANGLE_FACTOR, BASTARD_CUMULATIVE_SYNC_LOSS_ID_BASE, BASTARD_SYNC_LOSS_ID_BASE, BIT0, CALC_FUEL_IGN, CAM_SYNC, Clocks, coreStatusA, Counters, cumulativeBastardTeeth, cumulativeBastardTeethEroderCounter, KeyUserDebug::currentEvent, DEBUG_TURN_PIN_OFF, DEBUG_TURN_PIN_ON, DECODER_BENCHMARKS, KeyUserDebug::decoderFlags, edgeTimeStamp, KeyUserDebugs, lastAccumulatorCount, lastPARegisterReading, lastPrimaryEventTimeStamp, MAX_BASTARD_TEETH, MAX_CUMULATIVE_BASTARD_TEETH, NBIT0, NUMBER_OF_REAL_EVENTS, numberOfRealEvents, OK_TO_SCHEDULE, PACN1, PORTB, KeyUserDebug::primaryTeethSeen, PTIT, resetToNonRunningState(), sampleEachADC(), KeyUserDebug::secondaryTeethSeen, SET_SYNC_LEVEL_TO, Counter::syncedADCreadings, TC0, TFLG, TFLGOF, ticks_per_degree_multiplier, ticksPerDegreeRecord, LongTime::timeLong, Clock::timeoutADCreadingClock, timerExtensionClock, LongTime::timeShorts, timeStamp, windowCounts, windowsPerAllowedCumulativeBastardTooth, and windowState.

/* Clear the interrupt flag for this input compare channel */
TFLG = 0x01;
// Grab this first as it is the most critical var in this decoder
accumulatorRegisterCount = PACN1;/* save count before it changes */
/* Save all relevant available data here */
unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */
unsigned short edgeTimeStamp = TC0; /* Save the edge time stamp */
windowState = PTITCurrentState & 0x01; /* Save the high/low state of the port, HIGH PRIORITY some windows are only 2deg wide */
unsigned char accumulatorCount = accumulatorRegisterCount - lastPARegisterReading;/* save count before it changes */
lastPARegisterReading = accumulatorRegisterCount;
unsigned char i; /* temp loop var */
KeyUserDebugs.secondaryTeethSeen += accumulatorCount;
// DEBUG = accumulatorCount; // TODO remove DEBUG
/* always make sure you have two good counts(there are a few windows that share counts) */
// FRED do this on a per edge basis to lower chances of false match with +/- 1 counts
if(accumulatorCount == AMBIGUOUS_COUNT){
unsigned char lastEvent = 0xFF;
for(i = 0; numberOfRealEvents > i; i++){
if(windowCounts[i] == accumulatorCount){
if(i == 0){ /* keep our counter from going out of range */
KeyUserDebugs.currentEvent = 0xFF; // Will be rolled over to 0
lastEvent = NUMBER_OF_REAL_EVENTS - 1;
lastEvent = i - 1;
KeyUserDebugs.currentEvent = lastEvent; // Will be rolled up to current
if(lastEvent == 0xFF){ // Indicates that we didn't find a match, previously uncaught, would have occasionally matched last event with i = max and no match found on THIS event
}else if(windowCounts[lastEvent] == lastAccumulatorCount){ /* if true we are in sync! */
// TODO missedsync opportunity ++ or something
lastAccumulatorCount = accumulatorCount;
// TODO put fuzzy initial sync in place, maybe.
// // If still not synced, try to do fuzzy sync
// if(!(decoderFlags & CAM_SYNC)){
// // loop with +1 and -1
// // count fuzzy syncs, if genuine, should only be one + and one -
// // if not, give up and clear all state
// }
// return; // TODO remove and continue on down the thread
// Not an else block because the if block above can change the state of its own condition
if(KeyUserDebugs.currentEvent == numberOfRealEvents){ /* roll our event over if we are at the end */
* bastardTeeth will be zero if things are going well, and a low number
* if there is some latency, and a large number if totally wrong. This
* will not catch sequences of same direction errors, though. We need
* to keep a running track of past bastardTeeth too. TODO
signed char bastardTeeth = accumulatorCount - windowCounts[KeyUserDebugs.currentEvent];
cumulativeBastardTeeth += bastardTeeth;
// DEBUG = cumulativeBastardTeeth; // TODO remove DEBUG
// DEBUG = bastardTeeth;
// DEBUG = windowCounts[currentEvent]; // TODO remove DEBUG
// Cumulative Tolerance Code TODO add counters to monitor aggressiveness of this
// DEBUG++;
// counter for decrement
}else if(cumulativeBastardTeeth < 0){
// counter for increment
// counter for does nothing
/* if we are in-sync continue checking and perform required decoder calcs */
/* 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;
if((bastardTeeth > MAX_BASTARD_TEETH) || (bastardTeeth < -MAX_BASTARD_TEETH)){
resetToNonRunningState(BASTARD_SYNC_LOSS_ID_BASE + bastardTeeth); // TODO move this to the syncLossIDs.h header
}else{ // Tooth count was within spec
SET_SYNC_LEVEL_TO(CAM_SYNC); // Add confirmation until it is
/* TODO all required calcs etc as shown in other working decoders */
if((KeyUserDebugs.currentEvent % 2) == 1){ /* if we captured on a rising edge that is to say an evenly spaced edge perform the calcs */
// temporary data from inputs
unsigned long primaryLeadingEdgeTimeStamp = timeStamp.timeLong;
unsigned long timeBetweenSuccessivePrimaryPulses = primaryLeadingEdgeTimeStamp - lastPrimaryEventTimeStamp;
lastPrimaryEventTimeStamp = primaryLeadingEdgeTimeStamp;
/* RPM CALC, KISS for now and only run this part of the ISR when the edge has gone high
* this way we have evenly spaced teeth
*ticksPerDegreeRecord = (unsigned short)((ticks_per_degree_multiplier * timeBetweenSuccessivePrimaryPulses) / (90 * ANGLE_FACTOR));
// instead of above:
// save time difference
// have angle of time difference as setting
// do whole rpm calc in main loop to save ISR time, make more sense, and be more coherent to read
// then it's possible to use different tpdm figures for different RPM levels, thereby allowing a large range AND fine granularity!
// tpd would still need to be calculated for scheduling reasons, and the different scalings would need to be checked for overflow there.
// TODO Once sampling/RPM is configurable, use this tooth for a lower MAP reading.
/* Set flag to say calc required */
/* Reset the clock for reading timeout */

Here is the call graph for this function:

Variable Documentation

const unsigned short eventAngles[]
Initial value:
{ANGLE( 0), ANGLE( 86), ANGLE(130), ANGLE(176),
ANGLE(180), ANGLE(266), ANGLE(280), ANGLE(356),
ANGLE(360), ANGLE(446), ANGLE(470), ANGLE(536),
ANGLE(540), ANGLE(626), ANGLE(660), ANGLE(716)}

Definition at line 56 of file GM-LT1-CAS-360and8.c.

const unsigned char eventValidForCrankSync[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}

Definition at line 60 of file GM-LT1-CAS-360and8.c.

const unsigned char windowCounts[] = {4,86,44,46,4,86,14,76,4,86,24,66,4,86,34,56}

Definition at line 61 of file GM-LT1-CAS-360and8.c.

Referenced by PrimaryRPMISR().

unsigned char lastAccumulatorCount = 0xFF

Definition at line 62 of file GM-LT1-CAS-360and8.c.

Referenced by PrimaryRPMISR().

unsigned char lastPARegisterReading = 0xFF

Definition at line 63 of file GM-LT1-CAS-360and8.c.

Referenced by PrimaryRPMISR().

unsigned char windowState = 0

Definition at line 64 of file GM-LT1-CAS-360and8.c.

Referenced by PrimaryRPMISR().

unsigned char lastNumberOfRealEvents = 0

Definition at line 65 of file GM-LT1-CAS-360and8.c.

unsigned char accumulatorRegisterCount = 0

Definition at line 66 of file GM-LT1-CAS-360and8.c.

Referenced by PrimaryRPMISR().

signed char cumulativeBastardTeeth = 0

Definition at line 67 of file GM-LT1-CAS-360and8.c.

Referenced by perDecoderReset(), and PrimaryRPMISR().

unsigned short cumulativeBastardTeethEroderCounter = 0

Definition at line 85 of file GM-LT1-CAS-360and8.c.

Referenced by perDecoderReset(), and PrimaryRPMISR().