interrupts.h File Reference

All interrupt handler declarations. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define INT   __attribute__((interrupt))
#define ATOMIC_START()   __asm__ __volatile__ ("sei")
#define ATOMIC_END()   __asm__ __volatile__ ("cli")
#define VECTORS   __attribute__ ((section (".vectors")))

Typedefs

typedef void(* interruptTable )(void)

Functions

void _start (void)
void UISR (void) INT TEXT1
 Unimplemented Interrupt Handler.
void Injector1ISR (void) INT TEXT1
 Injector1ISR is expanded from InjectorXISR via include statement, and macro definition(s).
void Injector2ISR (void) INT TEXT1
 Injector2ISR is expanded from InjectorXISR via include statement, and macro definition(s).
void Injector3ISR (void) INT TEXT1
 Injector3ISR is expanded from InjectorXISR via include statement, and macro definition(s).
void Injector4ISR (void) INT TEXT1
 Injector4ISR is expanded from InjectorXISR via include statement, and macro definition(s).
void Injector5ISR (void) INT TEXT1
 Injector5ISR is expanded from InjectorXISR via include statement, and macro definition(s).
void Injector6ISR (void) INT TEXT1
 Injector6ISR is expanded from InjectorXISR via include statement, and macro definition(s).
void PrimaryRPMISR (void) INT TEXT1
void SecondaryRPMISR (void) INT TEXT1
 Use the rising and falling edges...................
void TimerOverflow (void) INT TEXT1
 ECT overflow handler.
void ModDownCtrISR (void) INT TEXT1
 Tacho pulse generator.
void IgnitionDwellISR (void) INT TEXT1
 Ignition dwell control.
void IgnitionFireISR (void) INT TEXT1
 Ignition discharge control.
void StagedOnISR (void) INT TEXT1
void StagedOffISR (void) INT TEXT1
void PortPISR (void) INT TEXT1
 Port P pins ISR.
void PortHISR (void) INT TEXT1
 Port H pins ISR.
void PortJISR (void) INT TEXT1
 Port J pins ISR.
void IRQISR (void) INT TEXT1
 IRQ/PE1 pin ISR.
void XIRQISR (void) INT TEXT1
 XIRQ/PE0 pin ISR.
void RTIISR (void) INT TEXT1
 Real Time Interrupt Handler.
void SCI0ISR (void) INT TEXT1
 Serial Communication Interface 0 ISR.
void LowVoltageISR (void) INT TEXT1
 Low Voltage Counter.
void VRegAPIISR (void) INT TEXT1

Detailed Description

All interrupt handler declarations.

All of the declarations for ISR functions are done here because they are all used in one place and it doesn't make sense to spread them out over N files for N functions. ISR headers only exist where there is a requirement for local variables and constants etc.

Author:
Fred Cooke

Definition in file interrupts.h.


Define Documentation

 
#define ATOMIC_END (  )     __asm__ __volatile__ ("cli")

Definition at line 61 of file interrupts.h.

Referenced by init(), and main().

 
#define ATOMIC_START (  )     __asm__ __volatile__ ("sei")

Definition at line 60 of file interrupts.h.

Referenced by init(), and main().

#define INT   __attribute__((interrupt))

Definition at line 53 of file interrupts.h.

#define VECTORS   __attribute__ ((section (".vectors")))

Definition at line 64 of file interrupts.h.


Typedef Documentation

typedef void(* interruptTable)(void)

Definition at line 107 of file interrupts.h.


Function Documentation

void _start ( void   ) 

Referenced by decodePacketAndRespond().

void IgnitionDwellISR ( void   ) 

Ignition dwell control.

This function turns ignition pins on to dwell when required.

Author:
Fred Cooke
Todo:
TODO make this actually work.

Definition at line 73 of file ignitionISRs.c.

References engineSetting::combustionEventsPerEngineCycle, DWELL_DISABLE, DWELL_ENABLE, dwellQueueLength, dwellStartMasks, fixedConfig1::engineSettings, fixedConfigs1, nextDwellChannel, PITCE, PITINTE, PITLD0, PITTF, PORTS, PORTS_BA, and queuedDwellOffsets.

00074 {
00075     // clear flag
00076     PITTF = DWELL_ENABLE;
00077 
00078     // start dwelling asap
00079     PORTS_BA |= dwellStartMasks[nextDwellChannel];
00080 
00081     if(dwellQueueLength == 0){
00082         // turn off the int
00083         PITINTE &= DWELL_DISABLE;
00084 
00085         // disable channels
00086         PITCE &= DWELL_DISABLE;
00087     }else{
00088         // reduce queue length by one
00089         dwellQueueLength--;
00090 
00091         // increment channel counter to next channel
00092         if(nextDwellChannel < (fixedConfigs1.engineSettings.combustionEventsPerEngineCycle - 1)){
00093             nextDwellChannel++; // if not the last channel, increment
00094         }else{
00095             nextDwellChannel = 0; // if the last channel, reset to zero
00096         }
00097 
00098         // if the queue length after decrement is greater than 0 then we need to load the timer, if it is zero and we decremented, the timer was already loaded.
00099         if(dwellQueueLength > 0){
00100             if(dwellQueueLength > 8){ // TODO ???? why 8 ???? 12 or combustion events per... or ?
00101                 //throw a nasty error of some sort for index out of range issue that should never occur (for now just light a LED)
00102                 PORTS |= 0x20;
00103             }else{
00104                 // load the timer if the index is good
00105                 PITLD0 = queuedDwellOffsets[dwellQueueLength - 1];
00106             }
00107         }
00108     }
00109 
00110     // blink a led
00111     PORTS ^= 0x80;
00112 }

void IgnitionFireISR ( void   ) 

Ignition discharge control.

This function turns ignition pins off to discharge when required.

Author:
Fred Cooke
Todo:
TODO make this actually work.

Definition at line 123 of file ignitionISRs.c.

References engineSetting::combustionEventsPerEngineCycle, fixedConfig1::engineSettings, fixedConfigs1, IGNITION_DISABLE, IGNITION_ENABLE, ignitionMasks, ignitionQueueLength, nextIgnitionChannel, PITCE, PITINTE, PITLD0, PITTF, PORTS, PORTS_BA, and queuedIgnitionOffsets.

00124 {
00125     // clear flag
00126     PITTF = IGNITION_ENABLE;
00127 
00128     // fire the coil asap
00129     PORTS_BA &= ignitionMasks[nextIgnitionChannel];
00130 
00131     if(ignitionQueueLength == 0){
00132         // turn off the int
00133         PITINTE &= IGNITION_DISABLE;
00134 
00135         // disable channels
00136         PITCE &= IGNITION_DISABLE ;
00137     }else{
00138         // reduce queue length by one
00139         ignitionQueueLength--;
00140 
00141         // increment channel counter to next channel
00142         if(nextIgnitionChannel < (fixedConfigs1.engineSettings.combustionEventsPerEngineCycle - 1)){
00143             nextIgnitionChannel++; // if not the last channel, increment
00144         }else{
00145             nextIgnitionChannel = 0; // if the last channel, reset to zero
00146         }
00147 
00148         // if the queue length after decrement is greater than 0 then we need to load the timer, if it is zero and we decremented, the timer was already loaded.
00149         if(ignitionQueueLength > 0){
00150             if(ignitionQueueLength > fixedConfigs1.engineSettings.combustionEventsPerEngineCycle){ // TODO as above!!!!!!!!!!
00151                 //throw a nasty error of some sort for index out of range issue that should never occur (for now just light a LED)
00152                 PORTS |= 0x10;
00153             }else{
00154                 // load the timer if the index is good
00155                 PITLD0 = queuedIgnitionOffsets[ignitionQueueLength - 1];
00156             }
00157         }
00158     }
00159 
00160     // blink a led
00161     PORTS ^= 0x40;
00162 }

void Injector1ISR ( void   ) 

Injector1ISR is expanded from InjectorXISR via include statement, and macro definition(s).

void Injector2ISR ( void   ) 

Injector2ISR is expanded from InjectorXISR via include statement, and macro definition(s).

void Injector3ISR ( void   ) 

Injector3ISR is expanded from InjectorXISR via include statement, and macro definition(s).

void Injector4ISR ( void   ) 

Injector4ISR is expanded from InjectorXISR via include statement, and macro definition(s).

void Injector5ISR ( void   ) 

Injector5ISR is expanded from InjectorXISR via include statement, and macro definition(s).

void Injector6ISR ( void   ) 

Injector6ISR is expanded from InjectorXISR via include statement, and macro definition(s).

void IRQISR ( void   ) 

IRQ/PE1 pin ISR.

Interrupt handler for edge events on the IRQ/PE1 pin. Not currently used.

Author:
Fred Cooke

Definition at line 203 of file miscISRs.c.

References Counter::callsToUISRs, and Counters.

00203                  {
00204     /* Clear the flag */
00205     // ?? TODO
00206 
00207     /* Increment the unimplemented ISR execution counter */
00208     Counters.callsToUISRs++;
00209 }

void LowVoltageISR ( void   ) 

Low Voltage Counter.

Count how often our voltage drops lower than it should without resetting.

Author:
Fred Cooke

Definition at line 233 of file miscISRs.c.

References Counters, Counter::lowVoltageConditions, and VREGCTRL.

00233                         {
00234     /* Clear the flag */
00235     VREGCTRL |= 0x01;
00236 
00237     /* Increment the counter */
00238     Counters.lowVoltageConditions++;
00239 }

void ModDownCtrISR ( void   ) 

Tacho pulse generator.

Currently this is being used to generate a variable frequency tachometer output. Although this is a bit of a waste of a timer resource it does allow tachometers that were intended for engines with a different cylinder count to be used where it would otherwise not be possible.

Author:
Fred Cooke

Definition at line 150 of file realtimeISRs.c.

References engineCyclePeriod, fixedConfigs1, MCCNT, MCFLG, PORTA, tachoPeriod, fixedConfig1::tachoSettings, tachoSetting::tachoTotalFactor, and ticksPerCycleAtOneRPM.

00150                     {
00151     /* Clear the modulus down counter interrupt flag */
00152     MCFLG = 0x80;
00153 
00154     /* If the rpm isn't genuine go ultra slow */
00155     if(engineCyclePeriod == ticksPerCycleAtOneRPM){
00156         tachoPeriod = 65535;
00157     }else{
00158         /* Use engine cycle period to setup the frequency of this counter and thereby act as a tacho out */
00159         tachoPeriod = (unsigned long)engineCyclePeriod / fixedConfigs1.tachoSettings.tachoTotalFactor;
00160     }
00161     /* Set the count down value */
00162     MCCNT = tachoPeriod;
00163 
00164     /* Bit bang the output port */
00165     PORTA ^= 0x40; // SM pin (A6)
00166 }

void PortHISR ( void   ) 

Port H pins ISR.

Interrupt handler for edge events on port H pins. Not currently used.

Author:
Fred Cooke

Definition at line 90 of file miscISRs.c.

References ONES, PIFH, PORTA, and portHDebounce.

00091 {
00092 //  // read the interrupt flags to a variable
00093 //  unsigned char portHFlags = PIFH;
00094 //  portHFlags &= 0xF8; // mask out the other bits
00095 //
00096 //  /* Clear all port H flags (we only want one at a time) */
00097     PIFH = ONES;
00098 //
00099 //  // Toggle a LED so we can see if the code ran
00100     PORTA ^= 0x80; // Fuel pump pin (A7)
00101 //
00102     // debounce
00103     if(portHDebounce == 0){
00104         portHDebounce = 2;
00105     }else{
00106         return;
00107     }
00108 //
00109 //  // find out which pin triggered it, clear the flag, perform the action.
00110 //  switch(portHFlags)
00111 //  {
00112 //  case 0x80 : // Increment cylinder count and set port count appropriately.
00113 //      switch (configs.combustionEventsPerEngineCycle) {
00114 //          case 1 :
00115 //              configs.combustionEventsPerEngineCycle = 2;
00116 //              configs.ports = 2;
00117 //              break;
00118 //          case 2 :
00119 //              configs.combustionEventsPerEngineCycle = 3;
00120 //              configs.ports = 3;
00121 //              break;
00122 //          case 3 :
00123 //              configs.combustionEventsPerEngineCycle = 4;
00124 //              configs.ports = 4;
00125 //              break;
00126 //          case 4 :
00127 //              configs.combustionEventsPerEngineCycle = 5;
00128 //              configs.ports = 5;
00129 //              break;
00130 //          case 5 :
00131 //              configs.combustionEventsPerEngineCycle = 6;
00132 //              configs.ports = 6;
00133 //              break;
00134 //          case 6 :
00135 //              configs.combustionEventsPerEngineCycle = 8;
00136 //              configs.ports = 4;
00137 //              break;
00138 //          case 8 :
00139 //              configs.combustionEventsPerEngineCycle = 10;
00140 //              configs.ports = 5;
00141 //              break;
00142 //          case 10 :
00143 //              configs.combustionEventsPerEngineCycle = 12;
00144 //              configs.ports = 6;
00145 //              break;
00146 //          case 12 :
00147 //              configs.combustionEventsPerEngineCycle = 1;
00148 //              configs.ports = 1;
00149 //              break;
00150 //      }
00151 //      break;
00152 //  case 0x40 : // Injection output enable/disable
00153 //      if(coreSettingsA & FUEL_CUT){
00154 //          coreSettingsA &= FUEL_CUT_OFF;
00155 //      }else{
00156 //          coreSettingsA |= FUEL_CUT;
00157 //      }
00158 //      break;
00159 //  case 0x20 : // Ignition output enable/disable
00160 //      if(coreSettingsA & HARD_SPARK_CUT){
00161 //          coreSettingsA &= HARD_SPARK_CUT_OFF;
00162 //      }else{
00163 //          coreSettingsA |= HARD_SPARK_CUT;
00164 //      }
00165 //      break;
00166 //  case 0x10 : // Staged injection enable/disable
00167 //      if(coreSettingsA & STAGED_ON){
00168 //          coreSettingsA &= STAGED_OFF;
00169 //      }else{
00170 //          coreSettingsA |= STAGED_ON;
00171 //      }
00172 //      break;
00173 //  case 0x08 : // Staged injection start sched/fixed
00174 //      if(coreSettingsA & STAGED_START){
00175 //          coreSettingsA &= CLEAR_STAGED_START;
00176 //      }else{
00177 //          coreSettingsA |= STAGED_START;
00178 //      }
00179 //      break;
00180 //  case 0x04 : // Staged injection end sched/fixed
00181 //      if(coreSettingsA & STAGED_END){
00182 //          coreSettingsA &= CLEAR_STAGED_END;
00183 //      }else{
00184 //          coreSettingsA |= STAGED_END;
00185 //      }
00186 //      break;
00187 //  case 0x02 : // free input
00188 //      break;
00189 //  case 0x01 : // free input
00190 //      break;
00191 //  default : // Two or more pressed, nothing to do except wait for another button press
00192 //      break;
00193 //  }
00194 }

void PortJISR ( void   ) 

Port J pins ISR.

Interrupt handler for edge events on port J pins. Not currently used.

Author:
Fred Cooke

Definition at line 76 of file miscISRs.c.

References Counter::callsToUISRs, Counters, ONES, and PIFJ.

00076                    {
00077     /* Clear all port H flags (we only want one at a time) */
00078     PIFJ = ONES;
00079     /* Increment the unimplemented ISR execution counter */
00080     Counters.callsToUISRs++;
00081 }

void PortPISR ( void   ) 

Port P pins ISR.

Interrupt handler for edge events on port P pins. Not currently used.

Author:
Fred Cooke

Definition at line 62 of file miscISRs.c.

References Counter::callsToUISRs, Counters, ONES, and PIFP.

00062                    {
00063     /* Clear all port P flags (we only want one at a time) */
00064     PIFP = ONES;
00065     /* Increment the unimplemented ISR execution counter */
00066     Counters.callsToUISRs++;
00067 }           /* Port P interrupt service routine */

void PrimaryRPMISR ( void   ) 

Primary RPM ISR

Todo:
TODO Docs here!

Primary RPM ISR

Todo:
TODO Docs here!

Primary RPM ISR

Todo:
TODO Docs here!

Primary RPM ISR

Summary of intended engine position capture scheme (out of date as at 3/1/09)

Position/RPM signal interpretation : Discard edges that have arrived too soon (lose sync here?) Check to ensure we haven't lost sync (pulse arrives too late) Compare time stamps of successive edges and calculate RPM Store RPM and position in globals

Schedule events : loop through all events (spark and fuel), schedule those that fall sufficiently after this tooth and before the next one we expect.

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.

Author:
Fred Cooke
Warning:
These are for testing and demonstration only, not suitable for driving with just yet.
Todo:

TODO bring the above docs up to date with reality

TODO finish this off to a usable standard

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.

Author:
Fred Cooke
Warning:
These are for testing and demonstration only, not suitable for driving with just yet.
Todo:
TODO make this code more general and robust such that it can be used for real simple applications

Primary RPM ISR

Todo:
TODO Docs here!

Todo:
TODO possibly add code to make sure we are in divide mode, if not error out
Todo:
TODO fill in or remove the else
Todo:
TODO discard narrow ones! test for tooth width and tooth period the width should be based on how the hardware is setup. IE the LM1815 is adjusted to have a pulse output of a particular width. This noise filter should be matched to that width as should the hardware filter.

Definition at line 72 of file LT1-360-8.c.

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

00072                         {
00073     /* Clear the interrupt flag for this input compare channel */
00074     TFLG = 0x01;
00075 
00076     /* Save all relevant available data here */
00077 //  unsigned short codeStartTimeStamp = TCNT;       /* Save the current timer count */
00078 //  unsigned short edgeTimeStamp = TC0;             /* Save the edge time stamp */
00079     unsigned char PTITCurrentState = PTIT;          /* Save the values on port T regardless of the state of DDRT */
00080 //  unsigned short PORTS_BACurrentState = PORTS_BA; /* Save ignition output state */
00081 
00082 //  unsigned char risingEdge; /* in LT1s case risingEdge means signal is high */
00083 //  if(fixedConfigs1.coreSettingsA & PRIMARY_POLARITY){
00084 //      risingEdge = PTITCurrentState & 0x01;
00085 //  }else{
00086 //      risingEdge = !(PTITCurrentState & 0x01);
00087 //  }
00088 
00089     PORTJ |= 0x80; /* Echo input condition on J7 */
00090     if(!isSynced){  /* If the CAS is not in sync get window counts so SecondaryRPMISR can set position */
00091         if (PTITCurrentState & 0x02){
00092             PrimaryTeethDuringHigh++;  /* if low resolution signal is high count number of pulses */
00093         }else{
00094             PrimaryTeethDuringLow++;  /* if low resolution signal is low count number of pulses */
00095         }
00096     }else{  /* The CAS is synced and we need to update our 360/5=72 tooth wheel */
00098         VCAS = VCAS + 10;  /* Check/correct for 10deg of CAM movement */
00100     }
00101 }

Here is the call graph for this function:

void RTIISR ( void   ) 

Real Time Interrupt Handler.

Handles time keeping, including all internal clocks, and generic periodic tasks that run quickly and must be done on time.

Author:
Fred Cooke

Definition at line 53 of file realtimeISRs.c.

References Clocks, coreStatusA, CRGFLG, fixedConfigs2, FORCE_READING, Clock::millisToTenths, portHDebounce, sensorSetting::readingTimeout, Clock::realTimeClockMain, Clock::realTimeClockMillis, Clock::realTimeClockMinutes, Clock::realTimeClockSeconds, Clock::realTimeClockTenths, RuntimeVar::RTCRuntime, RuntimeVars, Clock::secondsToMinutes, fixedConfig2::sensorSettings, ShouldSendLog, TCNT, Clock::tenthsToSeconds, Clock::timeoutADCreadingClock, TRUE, and XGSWT.

00053              {
00054     /* Clear the RTI flag */
00055     CRGFLG = 0x80;
00056 
00057     /* Record time stamp for code run time reporting */
00058     unsigned short startTimeRTI = TCNT;
00059 
00060     /* Increment the counter */
00061     Clocks.realTimeClockMain++;
00062 
00063     /* This function could be performed without the extra variables by rolling over the main ones at the largest multiples of the next ones, but I'm not sure thats better */
00064 
00065     // TODO add content to eighths of a milli RTC ?
00066 
00067     /* Every 8th RTI execution is one milli */
00068     if(Clocks.realTimeClockMain % 8 == 0){
00069         /* Increment the milli counter */
00070         Clocks.realTimeClockMillis++;
00071 
00072         /* Increment the milli roll over variable */
00073         Clocks.millisToTenths++;
00074 
00075         /* Perform all tasks that are once per millisecond here or preferably main */
00076         Clocks.timeoutADCreadingClock++;
00077         if(Clocks.timeoutADCreadingClock > fixedConfigs2.sensorSettings.readingTimeout){
00078             /* Set force read adc flag */
00079             coreStatusA |= FORCE_READING;
00080             Clocks.timeoutADCreadingClock = 0;
00081         }
00082 
00083         /* Every 100 millis is one tenth */
00084         if(Clocks.millisToTenths % 100 == 0){
00085             /* Increment the tenths counter */
00086             Clocks.realTimeClockTenths++;
00087 
00088             /* Increment the tenths roll over variable */
00089             Clocks.tenthsToSeconds++;
00090 
00091             /* Reset the millis roll over variable */
00092             Clocks.millisToTenths = 0;
00093 
00094             /* Perform all tasks that are once per tenth of a second here or preferably main */
00095             // decrement port H debounce variable till it's zero again.
00096             if(portHDebounce != 0){
00097                 portHDebounce -= 1;
00098             }
00099 
00100             /* Every 10 tenths is one second */
00101             if(Clocks.tenthsToSeconds % 10 == 0){
00102                 /* Increment the seconds counter */
00103                 Clocks.realTimeClockSeconds++;
00104                 XGSWT = 0x0101; /* set off software trigger 0 that is handled by xgate */
00105 
00106                 /* Increment the seconds roll over variable */
00107                 Clocks.secondsToMinutes++;
00108 
00109                 /* Reset the tenths roll over variable */
00110                 Clocks.tenthsToSeconds = 0;
00111                 /* Perform all tasks that are once per second here or preferably main */
00112 
00113                 // temp throttling for log due to tuner performance issues (in the bedroom)
00114                 ShouldSendLog = TRUE;
00115                 /* Flash the user LED as a "heartbeat" to let new users know it's alive */
00116                 //PORTP ^= 0x80;
00117 
00118                 /* Every 60 seconds is one minute, 65535 minutes is enough for us :-) */
00119                 if(Clocks.secondsToMinutes % 60 == 0){
00120                     /* Increment the minutes counter */
00121                     Clocks.realTimeClockMinutes++;
00122 
00123                     /* Potentially put an hours field in here and below, but that would be excessive */
00124                     // TODO add hours RTC ?
00125 
00126                     /* Reset the seconds roll over variable */
00127                     Clocks.secondsToMinutes = 0;
00128 
00129                     /* Perform all tasks that are once per minute here or preferably main */
00130                     // TODO add content in minutes RTC ?
00131 
00132                     /* Hours if statement here if we do hours which we probably won't */
00133                 }
00134             }
00135         }
00136     }
00137     RuntimeVars.RTCRuntime = TCNT - startTimeRTI;
00138 }

void SCI0ISR ( void   ) 

Serial Communication Interface 0 ISR.

SCI0 ISR handles all interrupts for SCI0 by reading flags and acting appropriately. Its functions are to send raw bytes out over the wire from a buffer and to receive bytes from the wire un-escape them, checksum them and store them in a buffer.

Author:
Fred Cooke
Todo:

TODO Move this code into an include file much like the fuel interrupts such that it can be used for multiple UART SCI devices without duplication.

TODO Remove the debug code that uses the IO ports to light LEDs during specific actions.

Definition at line 150 of file commsISRs.c.

References BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, CLEAR_ALL_SOURCE_ID_FLAGS, COM_CLEAR_SCI0_INTERFACE_ID, COM_SET_SCI0_INTERFACE_ID, Counter::commsChecksumMismatches, Counters, ESCAPE_BYTE, ESCAPED_ESCAPE_BYTE, ESCAPED_START_BYTE, ESCAPED_STOP_BYTE, PORTA, PORTB, receiveAndIncrement(), resetReceiveState(), RuntimeVars, RX_BUFFER_SIZE, RX_READY_TO_PROCESS, RX_SCI_ESCAPED_NEXT, RX_SCI_NOT_ESCAPED_NEXT, RXBufferContentSourceID, RXBufferCurrentPosition, RXCalculatedChecksum, RXPacketLengthReceived, RXStateFlags, SCI0CR2, SCI0DRL, SCI0SR1, SCICR2_RX_DISABLE, SCICR2_RX_ISR_DISABLE, SCICR2_RX_ISR_ENABLE, SCICR2_TX_ISR_DISABLE, SCICR2_TX_ISR_ENABLE, SCISR1_RX_FRAMING, SCISR1_RX_NOISE, SCISR1_RX_OVERRUN, SCISR1_RX_PARITY, SCISR1_RX_REGISTER_FULL, SCISR1_TX_REGISTER_EMPTY, sendAndIncrement(), Counter::serialEscapePairMismatches, Counter::serialFramingErrors, RuntimeVar::serialISRRuntime, Counter::serialNoiseErrors, Counter::serialOverrunErrors, Counter::serialPacketsOverLength, Counter::serialParityErrors, Counter::serialStartsInsideAPacket, START_BYTE, STOP_BYTE, TCNT, TXBufferCurrentPositionSCI0, TXBufferInUseFlags, TXByteEscaped, and TXPacketLengthToSendSCI0.

00150               {
00151     /* Read the flags register */
00152     unsigned char flags = SCI0SR1;
00153     /* Note: Combined with reading or writing the data register this also clears the flags. */
00154 
00155     /* Start counting */
00156     unsigned short start = TCNT;
00157 
00158     /* If the RX interrupt is enabled check RX related flags */
00159     if(SCI0CR2 & SCICR2_RX_ISR_ENABLE){
00160         /* Grab the received byte from the register */
00161         unsigned char rawByte = SCI0DRL;
00162 
00163         PORTB |= BIT0;
00164 
00165         /* Record error conditions always */
00166         unsigned char resetOnError = 0;
00167         /* If there is noise on the receive line record it */
00168         if(flags & SCISR1_RX_NOISE){
00169             Counters.serialNoiseErrors++;
00170             resetOnError++;
00171         }/* If an overrun occurs record it */
00172         if(flags & SCISR1_RX_OVERRUN){
00173             Counters.serialOverrunErrors++;
00174             resetOnError++;
00175         }/* If a framing error occurs record it */
00176         if(flags & SCISR1_RX_FRAMING){
00177             Counters.serialFramingErrors++;
00178             resetOnError++;
00179         }/* If a parity error occurs record it */
00180         if(flags & SCISR1_RX_PARITY){
00181             Counters.serialParityErrors++;
00182             resetOnError++;
00183         }
00184 
00185         /* Drop out because of error flags  */
00186         if(resetOnError){
00187             resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00188             PORTB |= BIT1;
00189             return;
00190         }
00191 
00192         /* If there is data waiting to be received */
00193         if(flags & SCISR1_RX_REGISTER_FULL){
00194             PORTB |= BIT2;
00195             /* Look for a start bresetReceiveStateyte to indicate a new packet */
00196             if(rawByte == START_BYTE){
00197                 PORTB |= BIT3;
00198                 /* If another interface is using it (Note, clear flag, not normal) */
00199                 if(RXBufferContentSourceID & COM_CLEAR_SCI0_INTERFACE_ID){
00200                     /* Turn off our reception */
00201                     SCI0CR2 &= SCICR2_RX_DISABLE;
00202                     SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00203                     PORTB |= BIT4;
00204                 }else{
00205                     PORTB |= BIT5;
00206                     /* If we are using it */
00207                     if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){
00208                         /* Increment the counter */
00209                         Counters.serialStartsInsideAPacket++;
00210                     }
00211                     /* Reset to us using it unless someone else was */
00212                     resetReceiveState(COM_SET_SCI0_INTERFACE_ID);
00213                 }
00214             }else if(RXPacketLengthReceived >= RX_BUFFER_SIZE){
00215                 /* Buffer was full, record and reset */
00216                 Counters.serialPacketsOverLength++;
00217                 resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00218                 PORTB |= BIT6;
00219             }else if(RXBufferContentSourceID & COM_SET_SCI0_INTERFACE_ID){
00220                 if(RXStateFlags & RX_SCI_ESCAPED_NEXT){
00221                     PORTB |= BIT7;
00222                     /* Clear escaped byte next flag, thanks Karsten! ((~ != !) == (! ~= ~)) == LOL */
00223                     RXStateFlags &= RX_SCI_NOT_ESCAPED_NEXT;
00224 
00225                     if(rawByte == ESCAPED_ESCAPE_BYTE){
00226                         /* Store and checksum escape byte */
00227                         receiveAndIncrement(ESCAPE_BYTE);
00228                     }else if(rawByte == ESCAPED_START_BYTE){
00229                         /* Store and checksum start byte */
00230                         receiveAndIncrement(START_BYTE);
00231                     }else if(rawByte == ESCAPED_STOP_BYTE){
00232                         /* Store and checksum stop byte */
00233                         receiveAndIncrement(STOP_BYTE);
00234                     }else{
00235                         /* Otherwise reset and record as data is bad */
00236                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00237                         Counters.serialEscapePairMismatches++;
00238                     }
00239                 }else if(rawByte == ESCAPE_BYTE){
00240                     PORTA |= BIT0;
00241                     /* Set flag to indicate that the next byte should be un-escaped. */
00242                     RXStateFlags |= RX_SCI_ESCAPED_NEXT;
00243                 }else if(rawByte == STOP_BYTE){
00244                     PORTA |= BIT1;
00245                     /* Turn off reception */
00246                     SCI0CR2 &= SCICR2_RX_DISABLE;
00247                     SCI0CR2 &= SCICR2_RX_ISR_DISABLE;
00248 
00249                     /* Bring the checksum back to where it should be */
00250                     unsigned char RXReceivedChecksum = (unsigned char)*(RXBufferCurrentPosition - 1);
00251                     RXCalculatedChecksum -= RXReceivedChecksum;
00252 
00253                     /* Check that the checksum matches */
00254                     if(RXCalculatedChecksum == RXReceivedChecksum){
00255                         /* If it's OK set process flag */
00256                         RXStateFlags |= RX_READY_TO_PROCESS;
00257                         PORTA |= BIT2;
00258                     }else{
00259                         PORTA |= BIT3;
00260                         /* Otherwise reset the state and record it */
00261                         resetReceiveState(CLEAR_ALL_SOURCE_ID_FLAGS);
00262                         Counters.commsChecksumMismatches++;
00263                     }
00264                 }else{
00265                     PORTA |= BIT4;
00266                     /* If it isn't special process it! */
00267                     receiveAndIncrement(rawByte);
00268                 }
00269             }else{
00270                 /* Do nothing : drop the byte */
00271                 PORTA |= BIT5;
00272             }
00273         }
00274     }
00275 
00276     /* If the TX interrupt is enabled check the register empty flag. */
00277     if((SCI0CR2 & SCICR2_TX_ISR_ENABLE) && (flags & SCISR1_TX_REGISTER_EMPTY)){
00278         /* Get the byte to be sent from the buffer */
00279         unsigned char rawValue = *TXBufferCurrentPositionSCI0;
00280 
00281         if(TXPacketLengthToSendSCI0 > 0){
00282             if(TXByteEscaped == 0){
00283                 /* If the raw value needs to be escaped */
00284                 if(rawValue == ESCAPE_BYTE){
00285                     SCI0DRL = ESCAPE_BYTE;
00286                     TXByteEscaped = ESCAPED_ESCAPE_BYTE;
00287                 }else if(rawValue == START_BYTE){
00288                     SCI0DRL = ESCAPE_BYTE;
00289                     TXByteEscaped = ESCAPED_START_BYTE;
00290                 }else if(rawValue == STOP_BYTE){
00291                     SCI0DRL = ESCAPE_BYTE;
00292                     TXByteEscaped = ESCAPED_STOP_BYTE;
00293                 }else{ /* Otherwise just send it */
00294                     sendAndIncrement(rawValue);
00295                 }
00296             }else{
00297                 sendAndIncrement(TXByteEscaped);
00298                 TXByteEscaped = 0;
00299             }
00300         }else{ /* Length is zero */
00301             /* Turn off transmission interrupt */
00302             SCI0CR2 &= SCICR2_TX_ISR_DISABLE;
00303             /* Send the stop byte */
00304             SCI0DRL = STOP_BYTE;
00305             while(!(SCI0SR1 & 0x80)){/* Wait for ever until able to send then move on */}
00306             SCI0DRL = STOP_BYTE; // nasty hack that works... means at least one and most 2 stops are sent so stuff works, but is messy... there must be a better way.
00307             /* Clear the TX in progress flag */
00308             TXBufferInUseFlags &= COM_CLEAR_SCI0_INTERFACE_ID;
00309         }
00310     }
00311 
00312     /* Record how long the operation took */
00313     RuntimeVars.serialISRRuntime = TCNT - start;
00314 }

Here is the call graph for this function:

void SecondaryRPMISR ( void   ) 

Use the rising and falling edges...................

Secondary RPM ISR

Todo:

TODO Docs here!

TODO Add a check for 1 skip pulse of the 8x track, to prevent possible incorrect sync.

TODO Possibly make virtual CAS 16-bit so was can get rid of floating points and use for syncing

Secondary RPM ISR

Todo:
TODO Docs here!

Secondary RPM ISR

Todo:
TODO Docs here!

Secondary RPM ISR

Similar to the primary one.

Todo:

TODO bring this documentation up to date.

TODO finish this off to a usable standard.

Secondary RPM ISR

Unused in this decoder.

Secondary RPM ISR

Todo:
TODO Docs here!

Todo:
TODO fill in or remove the else
Todo:
TODO discard narrow ones! test for tooth width and tooth period the width should be based on how the hardware is setup. IE the LM1815 is adjusted to have a pulse output of a particular width. This noise filter should be matched to that width as should the hardware filter.
Todo:
TODO discard narrow ones! test for tooth width and tooth period the width should be based on how the hardware is setup. IE the LM1815 is adjusted to have a pulse output of a particular width. This noise filter should be matched to that width as should the hardware filter.

Definition at line 110 of file LT1-360-8.c.

References changeSyncStatus(), CLEAR_PRIMARY_SYNC, fixedConfig1::coreSettingsA, coreStatusA, Counters, Counter::crankSyncLosses, engineCyclePeriod, fixedConfigs1, ISRLatencyVars, isSynced, lastSecondaryOddTimeStamp, lastSecondaryPulseLeadingTimeStamp, lastSecondaryPulseTrailingTimeStamp, lengthOfSecondaryLowPulses, PORTJ, PORTM, PRIMARY_POLARITY, PRIMARY_SYNC, primaryPulsesPerSecondaryPulse, PrimaryTeethDuringHigh, PrimaryTeethDuringLow, PTIT, RuntimeVars, SECONDARY_POLARITY, ISRLatencyVar::secondaryInputLatency, RuntimeVar::secondaryInputLeadingRuntime, RuntimeVar::secondaryInputTrailingRuntime, Counter::secondaryTeethSeen, TC1, TCNT, TFLG, TFLGOF, LongTime::timeLong, timerExtensionClock, LongTime::timeShorts, and VCAS.

00110                           {
00111     /* Clear the interrupt flag for this input compare channel */
00112     TFLG = 0x02;
00113 
00114     /* Save all relevant available data here */
00115 //  unsigned short codeStartTimeStamp = TCNT;       /* Save the current timer count */
00116 //  unsigned short edgeTimeStamp = TC1;             /* Save the timestamp */
00117     unsigned char PTITCurrentState = PTIT;          /* Save the values on port T regardless of the state of DDRT */
00118 //  unsigned short PORTS_BACurrentState = PORTS_BA; /* Save ignition output state */
00119     unsigned char risingEdge;
00120     if(fixedConfigs1.coreSettingsA & PRIMARY_POLARITY){
00121             risingEdge = PTITCurrentState & 0x01;
00122         }else{
00123             risingEdge = !(PTITCurrentState & 0x01);
00124         }
00125     PORTJ |= 0x40;  /* echo input condition */
00126 
00127     if (!isSynced & risingEdge){ /* If the CAS is not in sync get window counts and set virtual CAS position */
00128           /* if signal is high that means we can count the lows */
00129             switch (PrimaryTeethDuringLow){
00130             case 23: /* wheel is at 0 deg TDC #1, set our virtual CAS to tooth 0 of 720 */
00131             {
00132                 VCAS = 0 ;
00133                 changeSyncStatus((unsigned char) 1);
00134                 break;
00135             }
00136             case 38: /* wheel is at 90 deg TDC #4, set our virtual CAS to tooth 180 of 720 */
00137             {
00138                 VCAS = 180;
00139                 changeSyncStatus((unsigned char) 1);
00140                 break;
00141             }
00142             case 33: /* wheel is at 180 deg TDC #6 set our virtual CAS to tooth 360 of 720 */
00143             {
00144                 VCAS = 360;
00145                 changeSyncStatus((unsigned char) 1);
00146                 break;
00147             }
00148             case 28: /* wheel is at 270 deg TDC #7 set our virtual CAS to tooth 540 of 720 */
00149             {
00150                 VCAS = 540;
00151                 changeSyncStatus((unsigned char) 1);
00152                 break;
00153             }
00154             default :
00155             {
00156             Counters.crankSyncLosses++; /* use crankSyncLosses variable to store number of invalid count cases while attempting to sync*/
00157                 break;
00158             }
00159             PrimaryTeethDuringLow = 0; /* In any case reset counter */
00160             }
00161         }
00162     if(!isSynced & !risingEdge){/* if the signal is low that means we can count the highs */
00163             switch (PrimaryTeethDuringHigh){   /* will need to additional code to off-set the initialization of PACNT since they are not
00164                                                  evenly divisible by 5 */
00165             case 7: /* wheel is at 52 deg, 7 deg ATDC #8 set our virtual CAS to tooth 104 of 720 */
00166             {
00167 
00168                 break;
00169             }
00170             case 12: /* wheel is at 147 deg, 12 deg ATDC #3 set our virtual CAS to tooth 294 of 720 */
00171             {
00172 
00173                 break;
00174             }
00175             case 17: /* wheel is at 242 deg, 17 deg ATDC #5 set our virtual CAS to tooth 484 of 720 */
00176             {
00177 
00178                 break;
00179             }
00180             case 22: /* wheel is at 337 deg, 22 deg ATDC #2 set our virtual CAS to tooth 674 of 720 */
00181             {
00182 
00183                 break;
00184             }
00185             default :
00186             {
00187                 Counters.crankSyncLosses++; /* use crankSyncLosses variable to store number of invalid/default count cases while attempting to sync*/
00188                 break;
00189             }
00190 
00191             }
00192             PrimaryTeethDuringHigh = 0;  /* In any case reset counter */
00193         }
00194     if(isSynced & risingEdge){  /* We are in sync and need to make sure our counts are good */
00195 
00196         /* System is synced so use adjusted count numbers to check sync */
00198     }
00199 }

Here is the call graph for this function:

void StagedOffISR ( void   ) 

Definition at line 72 of file injectionISRs.c.

References PITINTE.

00072                        {
00073     // clear the flag
00074     PITINTE |= 0x08;
00075 
00076     // bit bang off the correct injector channel
00077     // TODO figure out which channel and switch it
00078     // TODO set the flag for that channel
00079 
00080     // if there are other staged channels pending, schedule them and adjust the data
00081     // TODO
00082 
00083     /* Clear the PIT3 flag */
00084     // TODO
00085 }

void StagedOnISR ( void   ) 

Definition at line 51 of file injectionISRs.c.

References fixedConfig1::coreSettingsA, fixedConfigs1, PITINTE, and STAGED_END.

00051                       {
00052     // clear the flag
00053     PITINTE |= 0x04;
00054 
00055     // bit bang on the correct injector channel
00056     // TODO figure out which channel and switch it
00057     // TODO set the flag for that channel
00058 
00059     // if there are other staged channels pending, schedule them and adjust the data
00060     // TODO
00061 
00062     /* If staged injection needs the end point scheduled, do it now (otherwise it will turn off naturally with the main injector) */
00063     if(!(fixedConfigs1.coreSettingsA & STAGED_END)){
00064         // TODO schedule the end of staged injection with PIT 3
00065     }
00066 
00067     /* Clear the PIT2 flag */
00068     // TODO
00069 }

void TimerOverflow ( void   ) 

ECT overflow handler.

When the ECT free running timer hits 65535 and rolls over, this is run. Its job is to extend the timer to an effective 32 bits for longer measuring much longer periods with the same resolution.

Author:
Fred Cooke

Definition at line 177 of file realtimeISRs.c.

References TFLGOF, and timerExtensionClock.

00177                     {
00178     /* Increment the timer extension variable */
00179     timerExtensionClock++;
00180 
00181     /* Clear the timer overflow interrupt flag */
00182     TFLGOF = 0x80;
00183 }

void UISR ( void   ) 

Unimplemented Interrupt Handler.

Unimplemented interrupt service routine for calls we weren't expecting. Currently this simply counts bad calls like any other event type.

Author:
Fred Cooke

Definition at line 50 of file miscISRs.c.

References Counter::callsToUISRs, and Counters.

00050                {
00051     /* Increment the unimplemented ISR execution counter */
00052     Counters.callsToUISRs++;
00053 }

void VRegAPIISR ( void   ) 
void XIRQISR ( void   ) 

XIRQ/PE0 pin ISR.

Interrupt handler for edge events on the XIRQ/PE0 pin. Not currently used.

Author:
Fred Cooke

Definition at line 218 of file miscISRs.c.

References Counter::callsToUISRs, and Counters.

00218                   {
00219     /* Clear the flag */
00220     // ?? TODO
00221 
00222     /* Increment the unimplemented ISR execution counter */
00223     Counters.callsToUISRs++;
00224 }

Generated on Sat Oct 16 21:29:16 2010 for FreeEMS by  doxygen 1.6.3