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