main.c File Reference

The main function! More...

#include "inc/main.h"

Include dependency graph for main.c:

Go to the source code of this file.

Functions

int main ()
 The main function!


Detailed Description

The main function!

The function main is traditionally an applications starting point. For us it has two jobs. The first is to call init() which initialises everything before any normal code runs. After that main() is simply an infinite loop from which low priority non-realtime code runs. The most important units of code that runs under the main loop umbrella are the injection, ignition and scheduling calculations.

Author:
Fred Cooke

Definition in file main.c.


Function Documentation

int main (  ) 

The main function!

The centre of the application is here. From here all non-ISR code is called directly or indirectly. The two coarse blocks are init and the main loop. Init is called first to set everything up and then the main loop is entered where the flow of control continues until the device is switched off or reset (excluding asynchronous ISR code). Currently the main loop only runs the fuel, ignition and scheduling calculation code, and only when actually required. The intention is to maintain a very low latency for calculations such that the behaviour of the device more closely reflects the attached engines rapidly changing requirements. When accessory code is added a new scheduling algorithm will be required to keep the latency low without starving any particular blocks of CPU time.

Author:
Fred Cooke

Definition at line 60 of file main.c.

References ADCArrays, ADCArrays0, ADCArrays1, ADCArraysRecord, adjustPWM(), asyncDatalogADC, asyncDatalogBasic, asyncDatalogCircBuf, asyncDatalogCircCAS, asyncDatalogConfig, asyncDatalogLogic, asyncDatalogOff, asyncDatalogTrigger, asyncDatalogType, ATOMIC_END, ATOMIC_START, BIT2, BIT3, CALC_FUEL_IGN, RuntimeVar::calcsRuntime, calculateFuelAndIgnition(), Counter::calculationsPerformed, checksumAndSend(), CLEAR_CALC_FUEL_IGN, CLEAR_FORCE_READING, COM_SET_SCI0_INTERFACE_ID, configuredBasicDatalogLength, coreStatusA, Counters, currentDwell0, currentDwell1, currentDwellMath, currentDwellRealtime, decodePacketAndRespond(), FALSE, FORCE_READING, RuntimeVar::genCoreVarsRuntime, RuntimeVar::genDerivedVarsRuntime, generateCoreVars(), generateDerivedVars(), HEADER_HAS_LENGTH, init(), injectorMainPulseWidths0, injectorMainPulseWidths1, injectorMainPulseWidthsMath, injectorMainPulseWidthsRealtime, injectorStagedPulseWidths0, injectorStagedPulseWidths1, injectorStagedPulseWidthsMath, injectorStagedPulseWidthsRealtime, ISRLatencyVars, ISRLatencyVar::mathLatency, mathSampleTimeStamp, ISRLatencyVar::mathSampleTimeStamp0, ISRLatencyVar::mathSampleTimeStamp1, mathSampleTimeStampRecord, RuntimeVar::mathSumRuntime, RuntimeVar::mathTotalRuntime, NBIT2, NBIT3, populateBasicDatalog(), PORTJ, PORTK, resetToNonRunningState(), responseBasicDatalog, RPM, RPM0, RPM1, RPMRecord, RuntimeVars, RX_CLEAR_READY_TO_PROCESS, RX_READY_TO_PROCESS, RXStateFlags, sampleEachADC(), SCI0CR2, SCICR2_RX_ENABLE, SCICR2_RX_ISR_ENABLE, ShouldSendLog, sleepMicro(), TCNT, Counter::timeoutADCreadings, TRUE, TXBufferCurrentPositionCAN0, TXBufferCurrentPositionHandler, TXBufferCurrentPositionSCI0, and TXBufferInUseFlags.

00060            { // TODO maybe move this to paged flash ?
00061     // Set everything up.
00062     init();
00063 
00064     //LongNoTime.timeLong = 54;
00065     // Run forever repeating.
00066     while(TRUE){
00067     //  unsigned short start = realTimeClockMillis;
00068         /* If ADCs require forced sampling, sample now */
00069         if(coreStatusA & FORCE_READING){
00070             ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
00071             /* Atomic block to ensure a full set of readings are taken together */
00072 
00073             /* Check to ensure that a reading wasn't take before we entered a non interruptable state */
00074             if(coreStatusA & FORCE_READING){ // do we still need to do this TODO ?
00075 
00076                 sampleEachADC(ADCArraysRecord); // TODO still need to do a pair of loops and clock these two functions for performance.
00077                 //sampleLoopADC(&ADCArrays);
00078                 resetToNonRunningState();
00079                 Counters.timeoutADCreadings++;
00080 
00081                 /* Set flag to say calc required */
00082                 coreStatusA |= CALC_FUEL_IGN;
00083 
00084                 /* Clear force reading flag */
00085                 coreStatusA &= CLEAR_FORCE_READING;
00086             }
00087 
00088             ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
00089         }
00090 
00091         /* If required, do main fuel and ignition calcs first */
00092         if(coreStatusA & CALC_FUEL_IGN){
00093             ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
00094             /* Atomic block to ensure that we don't clear the flag for the next data set when things are tight */
00095 
00096             /* Switch input bank so that we have a stable set of the latest data */
00097             if(ADCArrays == &ADCArrays1){
00098                 RPM = &RPM0; // TODO temp, remove
00099                 RPMRecord = &RPM1; // TODO temp, remove
00100                 ADCArrays = &ADCArrays0;
00101                 ADCArraysRecord = &ADCArrays1;
00102                 mathSampleTimeStamp = &ISRLatencyVars.mathSampleTimeStamp0; // TODO temp, remove
00103                 mathSampleTimeStampRecord = &ISRLatencyVars.mathSampleTimeStamp1; // TODO temp, remove
00104             }else{
00105                 RPM = &RPM1; // TODO temp, remove
00106                 RPMRecord = &RPM0; // TODO temp, remove
00107                 ADCArrays = &ADCArrays1;
00108                 ADCArraysRecord = &ADCArrays0;
00109                 mathSampleTimeStamp = &ISRLatencyVars.mathSampleTimeStamp1; // TODO temp, remove
00110                 mathSampleTimeStampRecord = &ISRLatencyVars.mathSampleTimeStamp0; // TODO temp, remove
00111             }
00112 
00113             /* Clear the calc required flag */
00114             coreStatusA &= CLEAR_CALC_FUEL_IGN;
00115 
00116             ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
00117 
00118             /* Store the latency from sample time to runtime */
00119             ISRLatencyVars.mathLatency = TCNT - *mathSampleTimeStamp;
00120             /* Keep track of how many calcs we are managing per second... */
00121             Counters.calculationsPerformed++;
00122             /* ...and how long they take each */
00123             unsigned short mathStartTime = TCNT;
00124 
00125             /* Generate the core variables from sensor input and recorded tooth timings */
00126             generateCoreVars();
00127 
00128             RuntimeVars.genCoreVarsRuntime = TCNT - mathStartTime;
00129             unsigned short derivedStartTime = TCNT;
00130 
00131             /* Generate the derived variables from the core variables based on settings */
00132             generateDerivedVars();
00133 
00134             RuntimeVars.genDerivedVarsRuntime = TCNT - derivedStartTime;
00135             unsigned short calcsStartTime = TCNT;
00136 
00137             /* Perform the calculations TODO possibly move this to the software interrupt if it makes sense to do so */
00138             calculateFuelAndIgnition();
00139 
00140             RuntimeVars.calcsRuntime = TCNT - calcsStartTime;
00141             /* Record the runtime of all the math total */
00142             RuntimeVars.mathTotalRuntime = TCNT - mathStartTime;
00143 
00144             RuntimeVars.mathSumRuntime = RuntimeVars.calcsRuntime + RuntimeVars.genCoreVarsRuntime + RuntimeVars.genDerivedVarsRuntime;
00145 
00146             ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
00147             /* Atomic block to ensure that outputBank and outputBank Offsets match */
00148 
00149             /* Switch banks to the latest data */
00150             if(injectorMainPulseWidthsMath == injectorMainPulseWidths1){
00151                 currentDwellMath = &currentDwell0;
00152                 currentDwellRealtime = &currentDwell1;
00153                 injectorMainPulseWidthsMath = injectorMainPulseWidths0;
00154                 injectorMainPulseWidthsRealtime = injectorMainPulseWidths1;
00155                 injectorStagedPulseWidthsMath = injectorStagedPulseWidths0;
00156                 injectorStagedPulseWidthsRealtime = injectorStagedPulseWidths1;
00157             }else{
00158                 currentDwellMath = &currentDwell1;
00159                 currentDwellRealtime = &currentDwell0;
00160                 injectorMainPulseWidthsMath = injectorMainPulseWidths1;
00161                 injectorMainPulseWidthsRealtime = injectorMainPulseWidths0;
00162                 injectorStagedPulseWidthsMath = injectorStagedPulseWidths1;
00163                 injectorStagedPulseWidthsRealtime = injectorStagedPulseWidths0;
00164             }
00165 
00166             ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
00167         }else{
00168             /* In the event that no calcs are required, sleep a little before returning to retry. */
00169             sleepMicro(RuntimeVars.mathTotalRuntime); // not doing this will cause the ISR lockouts to run for too high a proportion of the time
00170             /* Using 0.8 ticks as micros so it will run for a little longer than the math did */
00171         }
00172 
00173 
00174         if(!(TXBufferInUseFlags)){
00175         //  unsigned short logTimeBuffer = Clocks.realTimeClockTenths;
00176             /* If the flag for com packet processing is set and the TX buffer is available process the data! */
00177             if(RXStateFlags & RX_READY_TO_PROCESS){
00178                 /* Clear the flag */
00179                 RXStateFlags &= RX_CLEAR_READY_TO_PROCESS;
00180 
00181                 /* Handle the incoming packet */
00182                 decodePacketAndRespond();
00183             }else if(ShouldSendLog){//(lastTime != logTimeBuffer) && (lastCalcCount != Counters.calculationsPerformed)){
00184 
00185                 /* send asynchronous data log if required */
00186                 if(asyncDatalogType!= asyncDatalogOff){
00187                     switch (asyncDatalogType) {
00188                     case asyncDatalogBasic:
00189                     {
00190                         /* Flag that we are transmitting! */
00191                         TXBufferInUseFlags |= COM_SET_SCI0_INTERFACE_ID;
00192                         // SCI0 only for now...
00193 
00194                         // headers including length...                      *length = configuredBasicDatalogLength;
00195                         TXBufferCurrentPositionHandler = (unsigned char*)&TXBuffer;
00196 
00197                         /* Initialised here such that override is possible */
00198                         TXBufferCurrentPositionSCI0 = (unsigned char*)&TXBuffer;
00199                         TXBufferCurrentPositionCAN0 = (unsigned char*)&TXBuffer;
00200 
00201                         /* Set the flags : firmware, no ack, no addrs, has length */
00202                         *TXBufferCurrentPositionHandler = HEADER_HAS_LENGTH;
00203                         TXBufferCurrentPositionHandler++;
00204 
00205                         /* Set the payload ID */
00206                         *((unsigned short*)TXBufferCurrentPositionHandler) = responseBasicDatalog;
00207                         TXBufferCurrentPositionHandler += 2;
00208 
00209                         /* Set the length */
00210                         *((unsigned short*)TXBufferCurrentPositionHandler) = configuredBasicDatalogLength;
00211                         TXBufferCurrentPositionHandler += 2;
00212 
00213                         /* populate data log */
00214                         populateBasicDatalog();
00215                         checksumAndSend();
00216                         break;
00217                     }
00218                     case asyncDatalogConfig:
00219                     {
00220                         // TODO
00221                         break;
00222                     }
00223                     case asyncDatalogTrigger:
00224                     {
00225                         // TODO
00226                         break;
00227                     }
00228                     case asyncDatalogADC:
00229                     {
00230                         // TODO
00231                         break;
00232                     }
00233                     case asyncDatalogCircBuf:
00234                     {
00235                         // TODO
00236                         break;
00237                     }
00238                     case asyncDatalogCircCAS:
00239                     {
00240                         // TODO
00241                         break;
00242                     }
00243                     case asyncDatalogLogic:
00244                     {
00245                         // TODO
00246                         break;
00247                     }
00248                     }
00249                 }
00250                 ShouldSendLog = FALSE;
00251 //              // mechanism to ensure we send once per clock tick without doing it in the RTC section.
00252 //              lastTime = logTimeBuffer;
00253 //              // mechanism to ensure we only send something if the data has been updated
00254 //              lastCalcCount = Counters.calculationsPerformed;
00255             }
00256         }
00257         // on once per cycle for main loop heart beat (J0)
00258         PORTJ ^= 0x01;
00259 
00260 
00261         // debug...
00262         if(SCI0CR2 & SCICR2_RX_ENABLE){
00263             PORTK |= BIT2;
00264         }else{
00265             PORTK &= NBIT2;
00266         }
00267 
00268         if(SCI0CR2 & SCICR2_RX_ISR_ENABLE){
00269             PORTK |= BIT3;
00270         }else{
00271             PORTK &= NBIT3;
00272         }
00273 
00274         // PWM experimentation
00275         adjustPWM();
00276     }
00277 }

Here is the call graph for this function:


Generated on Mon Jan 26 00:17:09 2009 for FreeEMS by  doxygen 1.5.8