3 Copyright 2008 Fred Cooke
5 This file is part of the FreeEMS project.
7 FreeEMS software is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 FreeEMS software is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with any FreeEMS software. If not, see <http://www.gnu.org/licenses/>.
20 We ask that if you make any changes to this file you send them upstream to us at admin@diyefi.org
22 Thank you for choosing FreeEMS to run your engine! */
26 int main(){ // TODO maybe move this to paged flash ?
30 //LongNoTime.timeLong = 54;
31 // Run forever repeating.
34 // unsigned short start = realTimeClockMillis;
35 /* If ADCs require forced sampling, sample now */
36 if(coreStatusA
& FORCE_READING
){
37 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
38 /* Atomic block to ensure a full set of readings are taken together */
40 /* Check to ensure that a reading wasn't take before we entered a non interruptable state */
41 if(coreStatusA
& FORCE_READING
){ // do we still need to do this TODO ?
43 sampleEachADC(ADCArraysRecord
); // TODO still need to do a pair of loops and clock these two functions for performance.
44 //sampleLoopADC(&ADCArrays);
45 resetToNonRunningState();
46 Counters
.timeoutADCreadings
++;
48 /* Set flag to say calc required */
49 coreStatusA
|= CALC_FUEL_IGN
;
51 /* Clear force reading flag */
52 coreStatusA
&= CLEAR_FORCE_READING
;
55 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
58 /* If required, do main fuel and ignition calcs first */
59 if(coreStatusA
& CALC_FUEL_IGN
){
60 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
61 /* Atomic block to ensure that we don't clear the flag for the next data set when things are tight */
63 /* Switch input bank so that we have a stable set of the latest data */
64 if(ADCArrays
== &ADCArrays1
){
65 RPM
= &RPM0
; // TODO temp, remove
66 RPMRecord
= &RPM1
; // TODO temp, remove
67 ADCArrays
= &ADCArrays0
;
68 ADCArraysRecord
= &ADCArrays1
;
69 mathSampleTimeStamp
= &ISRLatencyVars
.mathSampleTimeStamp0
; // TODO temp, remove
70 mathSampleTimeStampRecord
= &ISRLatencyVars
.mathSampleTimeStamp1
; // TODO temp, remove
72 RPM
= &RPM1
; // TODO temp, remove
73 RPMRecord
= &RPM0
; // TODO temp, remove
74 ADCArrays
= &ADCArrays1
;
75 ADCArraysRecord
= &ADCArrays0
;
76 mathSampleTimeStamp
= &ISRLatencyVars
.mathSampleTimeStamp1
; // TODO temp, remove
77 mathSampleTimeStampRecord
= &ISRLatencyVars
.mathSampleTimeStamp0
; // TODO temp, remove
80 /* Clear the calc required flag */
81 coreStatusA
&= CLEAR_CALC_FUEL_IGN
;
83 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
85 /* Store the latency from sample time to runtime */
86 ISRLatencyVars
.mathLatency
= TCNT
- *mathSampleTimeStamp
;
87 /* Keep track of how many calcs we are managing per second... */
88 Counters
.calculationsPerformed
++;
89 /* ...and how long they take each */
90 unsigned short mathStartTime
= TCNT
;
92 /* Generate the core variables from sensor input and recorded tooth timings */
95 RuntimeVars
.genCoreVarsRuntime
= TCNT
- mathStartTime
;
96 unsigned short derivedStartTime
= TCNT
;
98 /* Generate the derived variables from the core variables based on settings */
99 generateDerivedVars();
101 RuntimeVars
.genDerivedVarsRuntime
= TCNT
- derivedStartTime
;
102 unsigned short calcsStartTime
= TCNT
;
104 /* Perform the calculations TODO possibly move this to the software interrupt if it makes sense to do so */
105 calculateFuelAndIgnition();
107 RuntimeVars
.calcsRuntime
= TCNT
- calcsStartTime
;
108 /* Record the runtime of all the math total */
109 RuntimeVars
.mathTotalRuntime
= TCNT
- mathStartTime
;
111 RuntimeVars
.mathSumRuntime
= RuntimeVars
.calcsRuntime
+ RuntimeVars
.genCoreVarsRuntime
+ RuntimeVars
.genDerivedVarsRuntime
;
113 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
114 /* Atomic block to ensure that outputBank and outputBank Offsets match */
116 /* Switch banks to the latest data */
117 if(injectorMainPulseWidthsMath
== injectorMainPulseWidths1
){
118 currentDwellMath
= ¤tDwell0
;
119 currentDwellRealtime
= ¤tDwell1
;
120 injectorMainPulseWidthsMath
= injectorMainPulseWidths0
;
121 injectorMainPulseWidthsRealtime
= injectorMainPulseWidths1
;
122 injectorStagedPulseWidthsMath
= injectorStagedPulseWidths0
;
123 injectorStagedPulseWidthsRealtime
= injectorStagedPulseWidths1
;
125 currentDwellMath
= ¤tDwell1
;
126 currentDwellRealtime
= ¤tDwell0
;
127 injectorMainPulseWidthsMath
= injectorMainPulseWidths1
;
128 injectorMainPulseWidthsRealtime
= injectorMainPulseWidths0
;
129 injectorStagedPulseWidthsMath
= injectorStagedPulseWidths1
;
130 injectorStagedPulseWidthsRealtime
= injectorStagedPulseWidths0
;
133 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
135 /* In the event that no calcs are required, sleep a little before returning to retry. */
136 sleepMicro(RuntimeVars
.mathTotalRuntime
); // not doing this will cause the ISR lockouts to run for too high a proportion of the time
137 /* Using 0.8 ticks as micros so it will run for a little longer than the math did */
141 if(!(TXBufferInUseFlags
)){
142 // unsigned short logTimeBuffer = Clocks.realTimeClockTenths;
143 /* If the flag for com packet processing is set and the TX buffer is available process the data! */
144 if(RXStateFlags
& RX_READY_TO_PROCESS
){
146 RXStateFlags
&= RX_CLEAR_READY_TO_PROCESS
;
148 /* Handle the incoming packet */
149 decodePacketAndRespond();
150 }else if(ShouldSendLog
){//(lastTime != logTimeBuffer) && (lastCalcCount != Counters.calculationsPerformed)){
152 /* send asynchronous data log if required */
153 if(asyncDatalogType
!= asyncDatalogOff
){
154 switch (asyncDatalogType
) {
155 case asyncDatalogBasic
:
157 /* Flag that we are transmitting! */
158 TXBufferInUseFlags
|= COM_SET_SCI0_INTERFACE_ID
;
159 // SCI0 only for now...
161 // headers including length... *length = configuredBasicDatalogLength;
162 TXBufferCurrentPositionHandler
= (unsigned char*)&TXBuffer
;
164 /* Initialised here such that override is possible */
165 TXBufferCurrentPositionSCI0
= (unsigned char*)&TXBuffer
;
166 TXBufferCurrentPositionCAN0
= (unsigned char*)&TXBuffer
;
168 /* Set the flags : firmware, no ack, no addrs, has length */
169 *TXBufferCurrentPositionHandler
= HEADER_HAS_LENGTH
;
170 TXBufferCurrentPositionHandler
++;
172 /* Set the payload ID */
173 *((unsigned short*)TXBufferCurrentPositionHandler
) = responseBasicDatalog
;
174 TXBufferCurrentPositionHandler
+= 2;
177 *((unsigned short*)TXBufferCurrentPositionHandler
) = configuredBasicDatalogLength
;
178 TXBufferCurrentPositionHandler
+= 2;
180 /* populate data log */
181 populateBasicDatalog();
185 case asyncDatalogConfig
:
190 case asyncDatalogTrigger
:
195 case asyncDatalogADC
:
200 case asyncDatalogCircBuf
:
205 case asyncDatalogCircCAS
:
210 case asyncDatalogLogic
:
217 ShouldSendLog
= FALSE
;
218 // // mechanism to ensure we send once per clock tick without doing it in the RTC section.
219 // lastTime = logTimeBuffer;
220 // // mechanism to ensure we only send something if the data has been updated
221 // lastCalcCount = Counters.calculationsPerformed;
224 // on once per cycle for main loop heart beat (J0)
229 if(SCI0CR2
& SCICR2_RX_ENABLE
){
235 if(SCI0CR2
& SCICR2_RX_ISR_ENABLE
){
241 // PWM experimentation