00001 /* FreeEMS - the open source engine management system 00002 * 00003 * Copyright 2008, 2009, 2010 Fred Cooke 00004 * 00005 * This file is part of the FreeEMS project. 00006 * 00007 * FreeEMS software is free software: you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation, either version 3 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * FreeEMS software is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with any FreeEMS software. If not, see http://www.gnu.org/licenses/ 00019 * 00020 * We ask that if you make any changes to this file you email them upstream to 00021 * us at admin(at)diyefi(dot)org or, even better, fork the code on github.com! 00022 * 00023 * Thank you for choosing FreeEMS to run your engine! 00024 */ 00025 00026 00048 #include "inc/freeEMS.h" 00049 #include "inc/interrupts.h" 00050 #include "inc/DecoderInterface.h" 00051 #include "inc/utils.h" 00052 00053 00069 void PrimaryRPMISR(){ 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 } 00172 00173 00178 void SecondaryRPMISR(){ 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 }