00001 /* main.c 00002 00003 Copyright 2008 Fred Cooke 00004 00005 This file is part of the FreeEMS project. 00006 00007 FreeEMS software is free software: you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation, either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 FreeEMS software is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with any FreeEMS software. If not, see <http://www.gnu.org/licenses/>. 00019 00020 We ask that if you make any changes to this file you send them upstream to us at admin@diyefi.org 00021 00022 Thank you for choosing FreeEMS to run your engine! */ 00023 00024 #define MAIN_OR_GLOBALS 00025 #include "inc/main.h" 00026 00027 int main(){ 00028 // Set everything up. 00029 init(); 00030 00031 //LongNoTime.timeLong = 54; 00032 // Run forever repeating. 00033 while(TRUE){ 00034 adjustPWM(); 00035 // unsigned short start = realTimeClockMillis; 00036 /* If ADCs require forced sampling, sample now */ 00037 if(coreStatusA & FORCE_READING){ 00038 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00039 /* Atomic block to ensure a full set of readings are taken together */ 00040 00041 /* Check to ensure that a reading wasn't take before we entered a non interruptable state */ 00042 if(coreStatusA & FORCE_READING){ // do we still need to do this TODO ? 00043 00044 sampleEachADC(&ADCArrays); // TODO still need to do a pair of loops and clock these two functions for performance. 00045 //sampleLoopADC(&ADCArrays); 00046 resetToNonRunningState(); 00047 Counters.timeoutADCreadingCounter++; 00048 00049 /* Set flag to say calc required */ 00050 coreStatusA |= CALC_FUEL_IGN; 00051 00052 /* Clear force reading flag */ 00053 coreStatusA &= CLEAR_FORCE_READING; 00054 } 00055 00056 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00057 } 00058 00059 /* If required, do main fuel and ignition calcs first */ 00060 if(coreStatusA & CALC_FUEL_IGN){ 00061 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00062 /* Atomic block to ensure that we don't clear the flag for the next data set when things are tight */ 00063 00064 /* Switch input bank so that we have a stable set of the latest data */ 00065 if(recordADCBank){ 00066 recordADCBank = 0; 00067 mathInputBank = 1; 00068 }else{ 00069 recordADCBank = 1; 00070 mathInputBank = 0; 00071 } 00072 00073 /* Clear the calc required flag */ 00074 coreStatusA &= CLEAR_CALC_FUEL_IGN; 00075 00076 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00077 00078 /* Store the latency from sample time to runtime */ 00079 ISRLatencyVars.mathLatency = TCNT - ISRLatencyVars.mathSampleTimeStamp[mathInputBank]; 00080 /* Keep track of how many calcs we are managing per second... */ 00081 Counters.calcsPerformedCounter++; 00082 /* ...and how long they take each */ 00083 unsigned short mathStartTime = TCNT; 00084 00085 /* Generate the core variables from sensor input and recorded tooth timings */ 00086 generateCoreVars(); 00087 00088 RuntimeVars.genCoreVarsRuntime = TCNT - mathStartTime; 00089 unsigned short derivedStartTime = TCNT; 00090 00091 /* Generate the derived variables from the core variables based on settings */ 00092 generateDerivedVars(); 00093 00094 RuntimeVars.genDerivedVarsRuntime = TCNT - derivedStartTime; 00095 unsigned short calcsStartTime = TCNT; 00096 00097 /* Perform the calculations TODO possibly move this to the software interrupt if it makes sense to do so */ 00098 calculateFuelAndIgnition(); 00099 00100 RuntimeVars.calcsRuntime = TCNT - calcsStartTime; 00101 /* Record the runtime of all the math total */ 00102 RuntimeVars.mathTotalRuntime = TCNT - mathStartTime; 00103 00104 RuntimeVars.mathSumRuntime = RuntimeVars.calcsRuntime + RuntimeVars.genCoreVarsRuntime + RuntimeVars.genDerivedVarsRuntime; 00105 00106 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00107 /* Atomic block to ensure that outputBank and outputBank Offsets match */ 00108 00109 /* Switch banks to the latest data */ 00110 if(mathInternalBank){ 00111 mathInternalBank = 0; 00112 mathInternalInjectionOffset = 0; 00113 mathInternalIgnitionOffset = 0; 00114 realTimeUseBank = 1; 00115 realTimeUseInjectionOffset = INJECTION_CHANNELS; 00116 realTimeUseIgnitionOffset = IGNITION_CHANNELS; 00117 }else{ 00118 mathInternalBank = 1; 00119 mathInternalInjectionOffset = INJECTION_CHANNELS; 00120 mathInternalIgnitionOffset = IGNITION_CHANNELS; 00121 realTimeUseBank = 0; 00122 realTimeUseInjectionOffset = 0; 00123 realTimeUseIgnitionOffset = 0; 00124 } 00125 00126 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ 00127 }else{ 00128 /* In the event that no calcs are required, sleep a little before returning to retry. */ 00129 sleepMicro(RuntimeVars.mathTotalRuntime); // not doing this will cause the ISR lockouts to run for too high a proportion of the time 00130 /* Using 0.8 ticks as micros so it will run for a little longer than the math did */ 00131 } 00132 00133 unsigned short logTimeBuffer = Clocks.realTimeClockTenths; 00134 00135 // send logging once per chosen clock tick 00136 if((lastTime != logTimeBuffer) && (lastCalcCount != Counters.calcsPerformedCounter)){ 00137 //sendHRLog(); 00138 // sendDebug("This is a call to all my past resignations!"); 00139 00140 sleepMicro(500); 00141 00142 // mechanism to ensure we send once per clock tick without doing it in the RTC section. 00143 lastTime = logTimeBuffer; 00144 // mechanism to ensure we only send something if the data has been updated 00145 lastCalcCount = Counters.calcsPerformedCounter; 00146 }else{ 00147 /* Balance out the loop for consistent running */ 00148 //sleepMicro(RuntimeVars.logSendingRuntime); 00149 sleepMicro(500); // temporary 00150 } 00151 00152 /* If the flag for com packet processing is set and the TX buffer is available process the data! */ 00153 if((RXStateFlags & RX_READY_TO_PROCESS) && !(TXBufferInUseFlags)){ 00154 /* Clear the flag */ 00155 RXStateFlags &= RX_CLEAR_READY_TO_PROCESS; 00156 00157 /* Handle the incoming packet */ 00158 decodePacketAndBuildResponse(); 00159 } 00160 00161 // on once per cycle for main loop heart beat (J0) 00162 PORTJ ^= 0x01; 00163 00164 00165 // debug... 00166 if(SCI0CR2 & SCICR2_RX_ENABLE){ 00167 PORTK |= BIT2; 00168 }else{ 00169 PORTK &= NBIT2; 00170 } 00171 00172 if(SCI0CR2 & SCICR2_RX_ISR_ENABLE){ 00173 PORTK |= BIT3; 00174 }else{ 00175 PORTK &= NBIT3; 00176 } 00177 00178 // PWM experimentation 00179 adjustPWM(); 00180 } 00181 }