Reads any signal that is once per cylinder. More...
#include "inc/freeEMS.h"
#include "inc/interrupts.h"
#include "inc/DecoderInterface.h"
#include "inc/utils.h"
Go to the source code of this file.
Defines | |
#define | ticksPerMinute 75000000 |
Functions | |
void | PrimaryRPMISR () |
void | SecondaryRPMISR () |
Use the rising and falling edges................... |
Reads any signal that is once per cylinder.
This file contains the two interrupt service routines required for to build cleanly. However, only the first one is used due to the simple nature of it.
The functional ISR just blindly injects fuel for every input it receives. Thus a perfectly clean input is absolutely essential at this time.
Supported engines include: B230F
Definition in file Simple.c.
#define ticksPerMinute 75000000 |
Referenced by PrimaryRPMISR().
void PrimaryRPMISR | ( | void | ) |
Primary RPM ISR
Schedule events : Blindly start fuel pulses for each and every input pulse.
Sample ADCs : Grab a unified set of ADC readings at one time in a consistent crank location to eliminate engine cycle dependent noise. Set flag stating that New pulse, advance, etc should be calculated.
Definition at line 69 of file Simple.c.
References ADCArrays, CALC_FUEL_IGN, Clocks, coreStatusA, Counters, engineCyclePeriod, injectorMainControlRegisters, injectorMainEnableMasks, injectorMainEndTimes, injectorMainOnMasks, injectorMainStartTimesHolding, injectorMainTimeRegisters, injectorMinimumPulseWidth, injectorSwitchOffCodeTime, ISRLatencyVars, lastPrimaryPulseTimeStamp, LONGHALF, masterPulseWidth, mathSampleTimeStampRecord, PORTJ, PRIMARY_SYNC, ISRLatencyVar::primaryInputLatency, RuntimeVar::primaryInputLeadingRuntime, RuntimeVar::primaryInputTrailingRuntime, primaryLeadingEdgeTimeStamp, Counter::primaryTeethSeen, PTIT, RPMRecord, RuntimeVars, sampleEachADC(), selfSetTimer, Counter::syncedADCreadings, TC0, TCNT, TFLG, TFLGOF, ticksPerMinute, TIE, timeBetweenSuccessivePrimaryPulses, LongTime::timeLong, Clock::timeoutADCreadingClock, timerExtensionClock, LongTime::timeShorts, totalAngleAfterReferenceInjection, and trailingEdgeSecondaryRPMInputCodeTime.
00069 { 00070 /* Clear the interrupt flag for this input compare channel */ 00071 TFLG = 0x01; 00072 00073 /* Save all relevant available data here */ 00074 unsigned short codeStartTimeStamp = TCNT; /* Save the current timer count */ 00075 unsigned short edgeTimeStamp = TC0; /* Save the edge time stamp */ 00076 unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */ 00077 00078 // set as synced for volvo always as loss of sync not actually possible 00079 coreStatusA |= PRIMARY_SYNC; 00080 00081 /* Calculate the latency in ticks */ 00082 ISRLatencyVars.primaryInputLatency = codeStartTimeStamp - edgeTimeStamp; 00083 00084 if(PTITCurrentState & 0x01){ 00085 /* Echo input condition on J7 */ 00086 PORTJ |= 0x80; 00087 00088 Counters.primaryTeethSeen++; 00089 00090 LongTime timeStamp; 00091 00092 /* Install the low word */ 00093 timeStamp.timeShorts[1] = edgeTimeStamp; 00094 /* Find out what our timer value means and put it in the high word */ 00095 if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */ 00096 timeStamp.timeShorts[0] = timerExtensionClock + 1; 00097 }else{ 00098 timeStamp.timeShorts[0] = timerExtensionClock; 00099 } 00100 00101 // temporary data from inputs 00102 primaryLeadingEdgeTimeStamp = timeStamp.timeLong; 00103 timeBetweenSuccessivePrimaryPulses = primaryLeadingEdgeTimeStamp - lastPrimaryPulseTimeStamp; 00104 lastPrimaryPulseTimeStamp = primaryLeadingEdgeTimeStamp; 00105 00106 // = 60 * (1000000 / 0.8) 00107 #define ticksPerMinute 75000000 // this is correct. 00108 00109 *RPMRecord = (unsigned short) (ticksPerMinute / timeBetweenSuccessivePrimaryPulses); 00110 00111 // TODO sample ADCs on teeth other than that used by the scheduler in order to minimise peak run time and get clean signals 00112 sampleEachADC(ADCArrays); 00113 Counters.syncedADCreadings++; 00114 *mathSampleTimeStampRecord = TCNT; 00115 00116 /* Set flag to say calc required */ 00117 coreStatusA |= CALC_FUEL_IGN; 00118 00119 /* Reset the clock for reading timeout */ 00120 Clocks.timeoutADCreadingClock = 0; 00121 00122 if(masterPulseWidth > injectorMinimumPulseWidth){ // use reference PW to decide. spark needs moving outside this area though TODO 00123 /* Determine if half the cycle is bigger than short-max */ 00124 unsigned short maxAngleAfter; 00125 if((engineCyclePeriod >> 1) > 0xFFFF){ 00126 maxAngleAfter = 0xFFFF; 00127 }else{ 00128 maxAngleAfter = (unsigned short)(engineCyclePeriod >> 1); 00129 } 00130 00131 /* Check advance to ensure it is less than 1/2 of the previous engine cycle and more than codetime away */ 00132 unsigned short advance; 00133 if(totalAngleAfterReferenceInjection > maxAngleAfter){ // if too big, make it max 00134 advance = maxAngleAfter; 00135 }else if(totalAngleAfterReferenceInjection < trailingEdgeSecondaryRPMInputCodeTime){ // if too small, make it min 00136 advance = trailingEdgeSecondaryRPMInputCodeTime; 00137 }else{ // else use it as is 00138 advance = totalAngleAfterReferenceInjection; 00139 } 00140 00141 // determine the long and short start times 00142 unsigned short startTime = edgeTimeStamp + advance; 00143 unsigned long startTimeLong = timeStamp.timeLong + advance; 00144 00145 /* Determine the channels to schedule */ 00146 unsigned char fuelChannel = 0;//(primaryPulsesPerSecondaryPulse / 2) - 1; 00147 00148 // determine whether or not to reschedule 00149 unsigned char reschedule = 0; 00150 unsigned long diff = startTimeLong - (injectorMainEndTimes[fuelChannel] + injectorSwitchOffCodeTime); 00151 if(diff > LONGHALF){ 00152 reschedule = 1; // http://www.diyefi.org/forum/viewtopic.php?f=8&t=57&p=861#p861 00153 } 00154 00155 // schedule the appropriate channel 00156 if(!(*injectorMainControlRegisters[fuelChannel] & injectorMainEnableMasks[fuelChannel]) || reschedule){ /* If the timer isn't still running, or if its set too long, set it to start again at the right time soon */ 00157 *injectorMainControlRegisters[fuelChannel] |= injectorMainEnableMasks[fuelChannel]; 00158 *injectorMainTimeRegisters[fuelChannel] = startTime; 00159 TIE |= injectorMainOnMasks[fuelChannel]; 00160 TFLG = injectorMainOnMasks[fuelChannel]; 00161 }else{ 00162 injectorMainStartTimesHolding[fuelChannel] = startTime; 00163 selfSetTimer |= injectorMainOnMasks[fuelChannel]; // setup a bit to let the timer interrupt know to set its own new start from a var 00164 } 00165 } 00166 RuntimeVars.primaryInputLeadingRuntime = TCNT - codeStartTimeStamp; 00167 }else{ 00168 PORTJ &= 0x7F; 00169 RuntimeVars.primaryInputTrailingRuntime = TCNT - codeStartTimeStamp; 00170 } 00171 }
void SecondaryRPMISR | ( | void | ) |
Use the rising and falling edges...................
Secondary RPM ISR
Unused in this decoder.
Definition at line 178 of file Simple.c.
References Counters, ISRLatencyVars, lastSecondaryPulseLeadingTimeStamp, lastSecondaryPulseTrailingTimeStamp, lengthOfSecondaryLowPulses, PORTJ, PTIT, ISRLatencyVar::secondaryInputLatency, Counter::secondaryTeethSeen, TC1, TCNT, TFLG, TFLGOF, LongTime::timeLong, timerExtensionClock, and LongTime::timeShorts.
00178 { 00179 /* Clear the interrupt flag for this input compare channel */ 00180 TFLG = 0x02; 00181 00182 /* Save all relevant available data here */ 00183 unsigned short codeStartTimeStamp = TCNT; /* Save the current timer count */ 00184 unsigned short edgeTimeStamp = TC1; /* Save the timestamp */ 00185 unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */ 00186 // unsigned short PORTS_BACurrentState = PORTS_BA; /* Save ignition output state */ 00187 00188 /* Calculate the latency in ticks */ 00189 ISRLatencyVars.secondaryInputLatency = codeStartTimeStamp - edgeTimeStamp; 00190 00197 LongTime timeStamp; 00198 00199 /* Install the low word */ 00200 timeStamp.timeShorts[1] = edgeTimeStamp; 00201 /* Find out what our timer value means and put it in the high word */ 00202 if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */ 00203 timeStamp.timeShorts[0] = timerExtensionClock + 1; 00204 }else{ 00205 timeStamp.timeShorts[0] = timerExtensionClock; 00206 } 00207 00208 /* The LM1815 variable reluctance sensor amplifier allows the output to be 00209 * pulled high starting at the center of a tooth. So, what we see as the 00210 * start of a tooth is actually the centre of a physical tooth. Because 00211 * tooth shape, profile and spacing may vary this is the only reliable edge 00212 * for us to schedule from, hence the trailing edge code is very simple. 00213 */ 00214 if(PTITCurrentState & 0x02){ 00215 // echo input condition 00216 PORTJ |= 0x40; 00217 00218 Counters.secondaryTeethSeen++; 00219 00220 /* leading code 00221 * 00222 * subtract lastTrailing from currentLeading 00223 * record currentLeading as lastLeading 00224 * 00225 * record pw as highDuration 00226 */ 00227 lengthOfSecondaryLowPulses = timeStamp.timeLong - lastSecondaryPulseTrailingTimeStamp; 00228 lastSecondaryPulseLeadingTimeStamp = timeStamp.timeLong; 00229 }else{ 00230 00231 /* trailing code 00232 * 00233 * subtract lastLeading from currentTrailing 00234 * record currentTrailing as lastTrailing 00235 * 00236 * record pw as lowDuration 00237 */ 00238 // lengthOfSecondaryHighPulses = timeStamp.timeLong - lastSecondaryPulseLeadingTimeStamp; 00239 lastSecondaryPulseTrailingTimeStamp = timeStamp.timeLong; 00240 00241 PORTJ &= 0xBF; 00242 } 00243 }