00001 /* FreeEMS - the open source engine management system 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 email them upstream to 00021 us at admin(at)diyefi(dot)org or, even better, fork the code on github.com! 00022 00023 Thank you for choosing FreeEMS to run your engine! */ 00024 00025 00041 #include "inc/main.h" 00042 00043 00060 int main(){ // 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 = ¤tDwell0; 00152 currentDwellRealtime = ¤tDwell1; 00153 injectorMainPulseWidthsMath = injectorMainPulseWidths0; 00154 injectorMainPulseWidthsRealtime = injectorMainPulseWidths1; 00155 injectorStagedPulseWidthsMath = injectorStagedPulseWidths0; 00156 injectorStagedPulseWidthsRealtime = injectorStagedPulseWidths1; 00157 }else{ 00158 currentDwellMath = ¤tDwell1; 00159 currentDwellRealtime = ¤tDwell0; 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 }