main.c File Reference

The main function! More...

#include "inc/main.h"
#include "freeEMS.h"
#include "interrupts.h"
#include "utils.h"
#include "init.h"
#include "commsISRs.h"
#include "commsCore.h"
#include "coreVarsGenerator.h"
#include "derivedVarsGenerator.h"
#include "fuelAndIgnitionCalcs.h"
#include "DecoderInterface.h"
Include dependency graph for main.c:
This graph shows which files directly or indirectly include this file:

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 61 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(), 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.

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

Here is the call graph for this function:

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