enginePositionISRs.c File Reference

#include "inc/freeEMS.h"
#include "inc/interrupts.h"
#include "inc/utils.h"
#include "inc/commsISRs.h"
#include "inc/enginePositionISRs.h"

Include dependency graph for enginePositionISRs.c:

Go to the source code of this file.

Defines

#define ENGINEPOSITIONISRS_C

Functions

void PrimaryRPMISR (void)
void SecondaryRPMISR (void)


Define Documentation

#define ENGINEPOSITIONISRS_C

Definition at line 24 of file enginePositionISRs.c.


Function Documentation

void PrimaryRPMISR ( void   ) 

Definition at line 48 of file enginePositionISRs.c.

References ADCArrays, CALC_FUEL_IGN, CLEAR_PRIMARY_SYNC, Clocks, fixedConfig2::combustionEventsPerEngineCycle, fixedConfig1::coreSettingsA, coreStatusA, Counters, Counter::crankSyncLosses, DWELL_ENABLE, dwellQueueLength, engineCyclePeriod, fixedConfigs1, fixedConfigs2, IGNITION_ENABLE, ignitionQueueLength, injectorMainControlRegisters, injectorMainEnableMasks, injectorMainEndTimes, injectorMainOnMasks, injectorMainPulseWidthsRealtime, injectorMainStartTimesHolding, injectorMainTimeRegisters, injectorMinimumPulseWidth, injectorSwitchOffCodeTime, ISRLatencyVars, lastPrimaryPulseTimeStamp, LONGHALF, masterPulseWidth, mathSampleTimeStampRecord, nextDwellChannel, nextIgnitionChannel, PITCE, PITCNT0, PITCNT1, PITINTE, PITLD0, PITLD1, PITTF, PORTJ, PRIMARY_POLARITY, PRIMARY_SYNC, ISRLatencyVar::primaryInputLatency, RuntimeVar::primaryInputLeadingRuntime, RuntimeVar::primaryInputTrailingRuntime, primaryLeadingEdgeTimeStamp, primaryPulsesPerSecondaryPulse, primaryTeethDroppedFromLackOfSync, Counter::primaryTeethSeen, PTIT, queuedDwellOffsets, queuedIgnitionOffsets, RPMRecord, RuntimeVars, sampleBlockADC(), selfSetTimer, Counter::syncedADCreadings, TC0, TCNT, TFLG, TFLGOF, ticksPerCycleAtOneRPMx2, TIE, timeBetweenSuccessivePrimaryPulses, timeBetweenSuccessivePrimaryPulsesBuffer, LongTime::timeLong, Clock::timeoutADCreadingClock, timerExtensionClock, LongTime::timeShorts, totalAngleAfterReferenceInjection, and trailingEdgeSecondaryRPMInputCodeTime.

00049 {
00050         /* Clear the interrupt flag for this input compare channel */
00051         TFLG = 0x01;
00052 
00053         /* Save all relevant available data here */
00054         unsigned short codeStartTimeStamp = TCNT;               /* Save the current timer count */
00055         unsigned short edgeTimeStamp = TC0;                             /* Save the edge time stamp */
00056         unsigned char PTITCurrentState = PTIT;                  /* Save the values on port T regardless of the state of DDRT */
00057 //      unsigned short PORTS_BACurrentState = PORTS_BA; /* Save ignition output state */
00058 
00059         /* Calculate the latency in ticks */
00060         ISRLatencyVars.primaryInputLatency = codeStartTimeStamp - edgeTimeStamp;
00061 
00062         // TODO discard narrow ones! test for tooth width and tooth period
00063 
00064         /* Set up edges as per config */
00065         unsigned char risingEdge;
00066         if(fixedConfigs1.coreSettingsA & PRIMARY_POLARITY){
00067                 risingEdge = PTITCurrentState & 0x01;
00068         }else{
00069                 risingEdge = !(PTITCurrentState & 0x01);
00070         }
00071 
00072         if(risingEdge){
00073                 /* Echo input condition on J7 */
00074                 PORTJ |= 0x80;
00075 
00076                 // increment crank pulses TODO this needs to be wrapped in tooth period and width checking
00077                 primaryPulsesPerSecondaryPulse++;
00078 
00079                 // calculate rough rpm (this will be wrong when the var is used correctly)
00080                 *RPMRecord = ticksPerCycleAtOneRPMx2 / engineCyclePeriod; /* 0.8us ticks, 150mil = 2 x 60 seconds, times rpm scale factor of 2 */
00081 
00082                 // don't run until the second trigger has come in and the period is correct (VERY temporary)
00083                 if(!(coreStatusA & PRIMARY_SYNC)){
00084                         primaryTeethDroppedFromLackOfSync++;
00085                         return;
00086                 }
00087 
00088                 LongTime timeStamp;
00089 
00090                 /* Install the low word */
00091                 timeStamp.timeShorts[1] = edgeTimeStamp;
00092                 /* Find out what our timer value means and put it in the high word */
00093                 if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
00094                         timeStamp.timeShorts[0] = timerExtensionClock + 1;
00095                 }else{
00096                         timeStamp.timeShorts[0] = timerExtensionClock;
00097                 }
00098 
00099                 // temporary data from inputs
00100                 primaryLeadingEdgeTimeStamp = edgeTimeStamp;
00101                 timeBetweenSuccessivePrimaryPulses = lastPrimaryPulseTimeStamp - primaryLeadingEdgeTimeStamp;
00102                 lastPrimaryPulseTimeStamp = primaryLeadingEdgeTimeStamp;
00103                 timeBetweenSuccessivePrimaryPulsesBuffer = (timeBetweenSuccessivePrimaryPulses >> 1) + (timeBetweenSuccessivePrimaryPulsesBuffer >> 1);
00104 
00105                 // TODO make scheduling either fixed from boot with a limited range, OR preferrably if its practical scheduled on the fly to allow arbitrary advance and retard of both fuel and ignition.
00106 
00107                 /* Check for loss of sync by too high a count */
00108                 if(primaryPulsesPerSecondaryPulse > 12){
00109                         /* Increment the lost sync count */
00110                         Counters.crankSyncLosses++;
00111 
00112                         /* Clear synced status */
00113                         coreStatusA &= CLEAR_PRIMARY_SYNC;
00114 
00115                         /* Reset the count of teeth */
00116                         primaryPulsesPerSecondaryPulse = 0;
00117 
00118                         /* Get the hell out of here before we do something bad */
00119                         return;
00120                 }
00121 
00122                 // CAUTION came to me lying in bed half asleep idea :
00123 
00124                 // TODO move tooth selection to the calc loop in main such that this routine just iterates through an array of events and schedules those that are destined for this tooth.
00125 
00126                 // if ign enabled
00127                         // iterate through ignition first, schedule all of those
00128                         // iterate through dwell next, schedule all of those
00129                 // if fuel enabled
00130                         // iterate through main fuel next, schedule all of those
00131                         // if staging enabled and required
00132                                 // iterate through staged fuel last,
00133 
00134                 // TODO should make for a clean compact scheduling implementation. the fuel code doesn't care when/how it has started in the past, and hopefully ign will be the same.
00135 
00136                 // this will be done with an array and per tooth check in future
00137                 if((primaryPulsesPerSecondaryPulse % 2) == 0){
00138 
00139                         // TODO sample ADCs on teeth other than that used by the scheduler in order to minimise peak run time and get clean signals
00140                         sampleBlockADC(ADCArrays);
00141                         Counters.syncedADCreadings++;
00142                         *mathSampleTimeStampRecord = TCNT;
00143 
00144                         /* Set flag to say calc required */
00145                         coreStatusA |= CALC_FUEL_IGN;
00146 
00147                         /* Reset the clock for reading timeout */
00148                         Clocks.timeoutADCreadingClock = 0;
00149 
00150                         if(masterPulseWidth > injectorMinimumPulseWidth){ // use reference PW to decide. spark needs moving outside this area though TODO
00151                                 /* Determine if half the cycle is bigger than short-max */
00152                                 unsigned short maxAngleAfter;
00153                                 if((engineCyclePeriod >> 1) > 0xFFFF){
00154                                         maxAngleAfter = 0xFFFF;
00155                                 }else{
00156                                         maxAngleAfter = (unsigned short)(engineCyclePeriod >> 1);
00157                                 }
00158 
00159                                 /* Check advance to ensure it is less than 1/2 of the previous engine cycle and more than codetime away */
00160                                 unsigned short advance;
00161                                 if(totalAngleAfterReferenceInjection > maxAngleAfter){ // if too big, make it max
00162                                         advance = maxAngleAfter;
00163                                 }else if(totalAngleAfterReferenceInjection < trailingEdgeSecondaryRPMInputCodeTime){ // if too small, make it min
00164                                         advance = trailingEdgeSecondaryRPMInputCodeTime;
00165                                 }else{ // else use it as is
00166                                         advance = totalAngleAfterReferenceInjection;
00167                                 }
00168 
00169                                 // determine the long and short start times
00170                                 unsigned short startTime = primaryLeadingEdgeTimeStamp + advance;
00171                                 unsigned long startTimeLong = timeStamp.timeLong + advance;
00172 
00173                                 /* Determine the channels to schedule */
00174                                 unsigned char fuelChannel = (primaryPulsesPerSecondaryPulse / 2) - 1;
00175                                 unsigned char ignitionChannel = (primaryPulsesPerSecondaryPulse / 2) - 1;
00176 
00177                                 if(fuelChannel > 5 || ignitionChannel > 5){
00178 //                                      send("bad fuel : ");
00179         //                              sendUC(fuelChannel);
00180                 //                      send("bad  ign : ");
00181                         //              sendUC(ignitionChannel);
00182                                         return;
00183                                 }
00184 
00185                                 // determine whether or not to reschedule
00186                                 unsigned char reschedule = 0;
00187                                 unsigned long diff = startTimeLong - (injectorMainEndTimes[fuelChannel] + injectorSwitchOffCodeTime);
00188                                 if(diff > LONGHALF){
00189                                         reschedule = 1; // http://www.diyefi.org/forum/viewtopic.php?f=8&t=57&p=861#p861
00190                                 }
00191 
00192                                 // schedule the appropriate channel
00193                                 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 */
00194                                         *injectorMainControlRegisters[fuelChannel] |= injectorMainEnableMasks[fuelChannel];
00195                                         *injectorMainTimeRegisters[fuelChannel] = startTime;
00196                                         TIE |= injectorMainOnMasks[fuelChannel];
00197                                         TFLG = injectorMainOnMasks[fuelChannel];
00198                                 }else{
00199                                         injectorMainStartTimesHolding[fuelChannel] = startTime;
00200                                         selfSetTimer |= injectorMainOnMasks[fuelChannel]; // setup a bit to let the timer interrupt know to set its own new start from a var
00201                                 }
00202 
00203                                 // TODO advance/retard/dwell numbers all need range checking etc done. some of this should be done in the calculator section, and some here. currently none is done at all and for that reason, this will not work in a real system yet, if it works at all.
00204                                 // as do array indexs here and in the ISRs...
00205 
00206 
00207                                 // TODO implement mechanism for dropping a cylinder in event of over queueing or spark cut/round robin
00208                                 // important as ignition sequence disrupted when this occurs as it stands.
00209 
00210                                 // TODO check queue length checks to ensure we dont count up to somewhere we can never count down from. This could be causing the hanging long phenomina
00211 
00212                                 // DWELL
00213 
00214                                 // If dwell is not currently enabled, set it all up
00215                                 if(!(PITCE & DWELL_ENABLE)){
00216                                         /* Schedule Dwell event (do this first because it comes earliest. */
00217                                         // set the channel to fire
00218                                         nextDwellChannel = ignitionChannel;
00219 
00220                                         // set the time
00221                                         PITLD0 = advance;
00222                                         //                              PITLD0 = ignitionAdvances[ignitionChannel] - *currentDwellRealtime; BAD for various reasons!
00223 
00224                                         // clear the flags first as they apparently become set any old time whether enabled or not.
00225                                         PITTF |= DWELL_ENABLE;
00226 
00227                                         // turn on the ints
00228                                         PITINTE |= DWELL_ENABLE;
00229 
00230                                         // clear the flags first as they apparently become set any old time whether enabled or not.
00231                                         PITTF |= DWELL_ENABLE;
00232 
00233                                         // enable channels
00234                                         PITCE |= DWELL_ENABLE;
00235                                 }else if(dwellQueueLength == 0){
00236                                         // load time offset such that next period is correct
00237                                         PITLD0 = (advance - PITCNT0);
00238 
00239                                         // increment queue length
00240                                         dwellQueueLength++;
00241                                 }else if(dwellQueueLength > fixedConfigs2.combustionEventsPerEngineCycle){ //TODO sensible figures here for array index OOBE
00242                                         // do nothing, or increment a counter or something similar.
00243                                 }else{
00244                                         unsigned short sumOfDwells = PITLD0;
00245                                         // add up the prequeued time periods
00246 
00247                                         // queue = 1 pitld is all
00248                                         // queue = 2 one from 0 index of array AND pitld
00249 
00250                                         unsigned char index = 0;
00251                                         while(index < (dwellQueueLength -1)){
00252                                                 sumOfDwells += queuedDwellOffsets[index];
00253                                                 index++;
00254                                         }
00255                                         //                              for(index = 0;index < (dwellQueueLength -1);index++){ // is this right?
00256                                         //                                      sumOfDwells += queuedDwellOffsets[index];
00257                                         //                              }
00258 
00259                                         // store time offset in appropriate array location
00260                                         queuedDwellOffsets[dwellQueueLength - 1] = advance - (PITCNT0 + sumOfDwells);
00261 
00262                                         // increment queue length from one or more
00263                                         dwellQueueLength++;
00264                                 }
00265 
00266                                 // IGNITION experimental stuff
00267 
00268                                 // If ignition is not currently enabled, set it all up
00269                                 if(!(PITCE & IGNITION_ENABLE)){
00270                                         /* Schedule Ignition event (do this first because it comes earliest. */
00271                                         // set the channel to fire
00272                                         nextIgnitionChannel = ignitionChannel;
00273 
00274                                         // figure out the time to set the delay reg to
00275                                         PITLD1 = advance + injectorMainPulseWidthsRealtime[fuelChannel];
00276                                         //                              PITLD1 = ignitionAdvances[ignitionChannel + outputBankIgnitionOffset];
00277 
00278                                         // clear the flags first as they apparently become set any old time whether enabled or not.
00279                                         PITTF |= IGNITION_ENABLE;
00280 
00281                                         // turn on the ints
00282                                         PITINTE |= IGNITION_ENABLE;
00283 
00284                                         // clear the flags first as they apparently become set any old time whether enabled or not.
00285                                         PITTF |= IGNITION_ENABLE;
00286 
00287                                         // enable channels
00288                                         PITCE |= IGNITION_ENABLE;
00289                                 }else if(ignitionQueueLength == 0){
00290                                         // load timer register
00291                                         PITLD1 = ((advance + injectorMainPulseWidthsRealtime[fuelChannel]) - PITCNT1);
00292 
00293                                         // increment to 1
00294                                         ignitionQueueLength++;
00295                                 }else if(ignitionQueueLength > fixedConfigs2.combustionEventsPerEngineCycle){ //TODO sensible figures here for array index OOBE
00296                                         // do nothing, or increment a counter or something similar.
00297                                 }else{
00298                                         unsigned short sumOfIgnitions = PITLD1;
00299                                         // add up the prequeued time periods
00300 
00301                                         // queue = 1 pitld is all
00302                                         // queue = 2 one from 0 index of array AND pitld
00303 
00304 
00305                                         unsigned char index = 0;
00306                                         while(index < (ignitionQueueLength - 1)){
00307                                                 sumOfIgnitions += queuedIgnitionOffsets[index];
00308                                                 index++;
00309                                         }
00310                                         //      for(index = 0;index < (ignitionQueueLength -1);index++){ // is this right?
00311                                         //              sumOfIgnitions += queuedIgnitionOffsets[index];
00312                                         //      }
00313 
00314                                         // store time offset in appropriate array location
00315                                         queuedIgnitionOffsets[ignitionQueueLength - 1] = advance - (PITCNT1 + sumOfIgnitions);
00316 
00317                                         // increment from 1 or more
00318                                         ignitionQueueLength++;
00319                                 }
00320                         }
00321                 }
00322                 RuntimeVars.primaryInputLeadingRuntime = TCNT - codeStartTimeStamp;
00323         }else{
00324                 PORTJ &= 0x7F;
00325                 RuntimeVars.primaryInputTrailingRuntime = TCNT - codeStartTimeStamp;
00326         }
00327 
00328         Counters.primaryTeethSeen++;
00329         // suss out rpm and accurate TDC reference
00330 
00331         // if you say it quick, it doesn't sound like much :
00332         // schedule fuel and ign based on spark cut and fuel cut and timing vars and status vars config vars
00333 }

Here is the call graph for this function:

void SecondaryRPMISR ( void   ) 

Definition at line 335 of file enginePositionISRs.c.

References CLEAR_PRIMARY_SYNC, fixedConfig1::coreSettingsA, coreStatusA, Counters, Counter::crankSyncLosses, engineCyclePeriod, fixedConfigs1, ISRLatencyVars, lastSecondaryOddTimeStamp, PORTJ, PORTM, PRIMARY_SYNC, primaryPulsesPerSecondaryPulse, primaryPulsesPerSecondaryPulseBuffer, PTIT, RuntimeVars, SECONDARY_POLARITY, ISRLatencyVar::secondaryInputLatency, RuntimeVar::secondaryInputLeadingRuntime, RuntimeVar::secondaryInputTrailingRuntime, Counter::secondaryTeethSeen, TC1, TCNT, TFLG, TFLGOF, LongTime::timeLong, timerExtensionClock, and LongTime::timeShorts.

00336 {
00337         /* Clear the interrupt flag for this input compare channel */
00338         TFLG = 0x02;
00339 
00340         /* Save all relevant available data here */
00341         unsigned short codeStartTimeStamp = TCNT;               /* Save the current timer count */
00342         unsigned short edgeTimeStamp = TC1;                             /* Save the timestamp */
00343         unsigned char PTITCurrentState = PTIT;                  /* Save the values on port T regardless of the state of DDRT */
00344 //      unsigned short PORTS_BACurrentState = PORTS_BA; /* Save ignition output state */
00345 
00346         /* Calculate the latency in ticks */
00347         ISRLatencyVars.secondaryInputLatency = codeStartTimeStamp - edgeTimeStamp;
00348 
00349         // TODO discard narrow ones! test for tooth width and tooth period
00350 
00351         /* Set up edges as per config */
00352         unsigned char risingEdge;
00353         if(fixedConfigs1.coreSettingsA & SECONDARY_POLARITY){
00354                 risingEdge = PTITCurrentState & 0x02;
00355         }else{
00356                 risingEdge = !(PTITCurrentState & 0x02);
00357         }
00358 
00359         if(risingEdge){
00360                 // echo input condition
00361                 PORTJ |= 0x40;
00362 
00363                 // display the crank pulses
00364                 PORTM = (char)primaryPulsesPerSecondaryPulseBuffer;
00365 
00366                 primaryPulsesPerSecondaryPulseBuffer = primaryPulsesPerSecondaryPulse;
00367                 primaryPulsesPerSecondaryPulse = 0;
00368 
00369                 // if we didn't get the right number of pulses drop sync and start over
00370                 if((primaryPulsesPerSecondaryPulseBuffer != 12) && (coreStatusA & PRIMARY_SYNC)){
00371                         coreStatusA &= CLEAR_PRIMARY_SYNC;
00372                         Counters.crankSyncLosses++;
00373                 }
00374 
00375                 LongTime timeStamp;
00376 
00377                 /* Install the low word */
00378                 timeStamp.timeShorts[1] = edgeTimeStamp;
00379                 /* Find out what our timer value means and put it in the high word */
00380                 if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
00381                         timeStamp.timeShorts[0] = timerExtensionClock + 1;
00382                 }else{
00383                         timeStamp.timeShorts[0] = timerExtensionClock;
00384                 }
00385 
00386                 // get the data we actually want
00387                 engineCyclePeriod = 2 * (timeStamp.timeLong - lastSecondaryOddTimeStamp); // save the engine cycle period
00388                 lastSecondaryOddTimeStamp = timeStamp.timeLong; // save this stamp for next time round
00389 
00390                 // Because this is our only reference, each time we get this pulse, we know where we are at (simple mode so far)
00391                 coreStatusA |= PRIMARY_SYNC;
00392                 RuntimeVars.secondaryInputLeadingRuntime = TCNT - codeStartTimeStamp;
00393         }else{
00394                 PORTJ &= 0xBF;
00395                 RuntimeVars.secondaryInputTrailingRuntime = TCNT - codeStartTimeStamp;
00396         }
00397 
00398         Counters.secondaryTeethSeen++;
00399         // suss out phase/engine cycle reference showing which bank we are on
00400 
00401         /* If the flag is not cleared at the beginning then the interrupt gets rescheduled while it is running, hence it can't be done at the end of the ISR */
00402 }


Generated on Mon Dec 22 21:29:41 2008 for freeems by  doxygen 1.5.2