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