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 email them upstream to
21 us at admin(at)diyefi(dot)org or, even better, fork the code on github.com!
23 Thank you for choosing FreeEMS to run your engine! */
29 int main(){ // TODO maybe move this to paged flash ?
33 //LongNoTime.timeLong = 54;
34 // Run forever repeating.
36 // unsigned short start = realTimeClockMillis;
37 /* If ADCs require forced sampling, sample now */
38 if(coreStatusA
& FORCE_READING
){
39 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
40 /* Atomic block to ensure a full set of readings are taken together */
42 /* Check to ensure that a reading wasn't take before we entered a non interruptable state */
43 if(coreStatusA
& FORCE_READING
){ // do we still need to do this TODO ?
45 sampleEachADC(ADCArraysRecord
); // TODO still need to do a pair of loops and clock these two functions for performance.
46 //sampleLoopADC(&ADCArrays);
47 resetToNonRunningState();
48 Counters
.timeoutADCreadings
++;
50 /* Set flag to say calc required */
51 coreStatusA
|= CALC_FUEL_IGN
;
53 /* Clear force reading flag */
54 coreStatusA
&= CLEAR_FORCE_READING
;
57 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
60 /* If required, do main fuel and ignition calcs first */
61 if(coreStatusA
& CALC_FUEL_IGN
){
62 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
63 /* Atomic block to ensure that we don't clear the flag for the next data set when things are tight */
65 /* Switch input bank so that we have a stable set of the latest data */
66 if(ADCArrays
== &ADCArrays1
){
67 RPM
= &RPM0
; // TODO temp, remove
68 RPMRecord
= &RPM1
; // TODO temp, remove
69 ADCArrays
= &ADCArrays0
;
70 ADCArraysRecord
= &ADCArrays1
;
71 mathSampleTimeStamp
= &ISRLatencyVars
.mathSampleTimeStamp0
; // TODO temp, remove
72 mathSampleTimeStampRecord
= &ISRLatencyVars
.mathSampleTimeStamp1
; // TODO temp, remove
74 RPM
= &RPM1
; // TODO temp, remove
75 RPMRecord
= &RPM0
; // TODO temp, remove
76 ADCArrays
= &ADCArrays1
;
77 ADCArraysRecord
= &ADCArrays0
;
78 mathSampleTimeStamp
= &ISRLatencyVars
.mathSampleTimeStamp1
; // TODO temp, remove
79 mathSampleTimeStampRecord
= &ISRLatencyVars
.mathSampleTimeStamp0
; // TODO temp, remove
82 /* Clear the calc required flag */
83 coreStatusA
&= CLEAR_CALC_FUEL_IGN
;
85 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
87 /* Store the latency from sample time to runtime */
88 ISRLatencyVars
.mathLatency
= TCNT
- *mathSampleTimeStamp
;
89 /* Keep track of how many calcs we are managing per second... */
90 Counters
.calculationsPerformed
++;
91 /* ...and how long they take each */
92 unsigned short mathStartTime
= TCNT
;
94 /* Generate the core variables from sensor input and recorded tooth timings */
97 RuntimeVars
.genCoreVarsRuntime
= TCNT
- mathStartTime
;
98 unsigned short derivedStartTime
= TCNT
;
100 /* Generate the derived variables from the core variables based on settings */
101 generateDerivedVars();
103 RuntimeVars
.genDerivedVarsRuntime
= TCNT
- derivedStartTime
;
104 unsigned short calcsStartTime
= TCNT
;
106 /* Perform the calculations TODO possibly move this to the software interrupt if it makes sense to do so */
107 calculateFuelAndIgnition();
109 RuntimeVars
.calcsRuntime
= TCNT
- calcsStartTime
;
110 /* Record the runtime of all the math total */
111 RuntimeVars
.mathTotalRuntime
= TCNT
- mathStartTime
;
113 RuntimeVars
.mathSumRuntime
= RuntimeVars
.calcsRuntime
+ RuntimeVars
.genCoreVarsRuntime
+ RuntimeVars
.genDerivedVarsRuntime
;
115 ATOMIC_START(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
116 /* Atomic block to ensure that outputBank and outputBank Offsets match */
118 /* Switch banks to the latest data */
119 if(injectorMainPulseWidthsMath
== injectorMainPulseWidths1
){
120 currentDwellMath
= ¤tDwell0
;
121 currentDwellRealtime
= ¤tDwell1
;
122 injectorMainPulseWidthsMath
= injectorMainPulseWidths0
;
123 injectorMainPulseWidthsRealtime
= injectorMainPulseWidths1
;
124 injectorStagedPulseWidthsMath
= injectorStagedPulseWidths0
;
125 injectorStagedPulseWidthsRealtime
= injectorStagedPulseWidths1
;
127 currentDwellMath
= ¤tDwell1
;
128 currentDwellRealtime
= ¤tDwell0
;
129 injectorMainPulseWidthsMath
= injectorMainPulseWidths1
;
130 injectorMainPulseWidthsRealtime
= injectorMainPulseWidths0
;
131 injectorStagedPulseWidthsMath
= injectorStagedPulseWidths1
;
132 injectorStagedPulseWidthsRealtime
= injectorStagedPulseWidths0
;
135 ATOMIC_END(); /*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
137 /* In the event that no calcs are required, sleep a little before returning to retry. */
138 sleepMicro(RuntimeVars
.mathTotalRuntime
); // not doing this will cause the ISR lockouts to run for too high a proportion of the time
139 /* Using 0.8 ticks as micros so it will run for a little longer than the math did */
143 if(!(TXBufferInUseFlags
)){
144 // unsigned short logTimeBuffer = Clocks.realTimeClockTenths;
145 /* If the flag for com packet processing is set and the TX buffer is available process the data! */
146 if(RXStateFlags
& RX_READY_TO_PROCESS
){
148 RXStateFlags
&= RX_CLEAR_READY_TO_PROCESS
;
150 /* Handle the incoming packet */
151 decodePacketAndRespond();
152 }else if(ShouldSendLog
){//(lastTime != logTimeBuffer) && (lastCalcCount != Counters.calculationsPerformed)){
154 /* send asynchronous data log if required */
155 if(asyncDatalogType
!= asyncDatalogOff
){
156 switch (asyncDatalogType
) {
157 case asyncDatalogBasic
:
159 /* Flag that we are transmitting! */
160 TXBufferInUseFlags
|= COM_SET_SCI0_INTERFACE_ID
;
161 // SCI0 only for now...
163 // headers including length... *length = configuredBasicDatalogLength;
164 TXBufferCurrentPositionHandler
= (unsigned char*)&TXBuffer
;
166 /* Initialised here such that override is possible */
167 TXBufferCurrentPositionSCI0
= (unsigned char*)&TXBuffer
;
168 TXBufferCurrentPositionCAN0
= (unsigned char*)&TXBuffer
;
170 /* Set the flags : firmware, no ack, no addrs, has length */
171 *TXBufferCurrentPositionHandler
= HEADER_HAS_LENGTH
;
172 TXBufferCurrentPositionHandler
++;
174 /* Set the payload ID */
175 *((unsigned short*)TXBufferCurrentPositionHandler
) = responseBasicDatalog
;
176 TXBufferCurrentPositionHandler
+= 2;
179 *((unsigned short*)TXBufferCurrentPositionHandler
) = configuredBasicDatalogLength
;
180 TXBufferCurrentPositionHandler
+= 2;
182 /* populate data log */
183 populateBasicDatalog();
187 case asyncDatalogConfig
:
192 case asyncDatalogTrigger
:
197 case asyncDatalogADC
:
202 case asyncDatalogCircBuf
:
207 case asyncDatalogCircCAS
:
212 case asyncDatalogLogic
:
219 ShouldSendLog
= FALSE
;
220 // // mechanism to ensure we send once per clock tick without doing it in the RTC section.
221 // lastTime = logTimeBuffer;
222 // // mechanism to ensure we only send something if the data has been updated
223 // lastCalcCount = Counters.calculationsPerformed;
226 // on once per cycle for main loop heart beat (J0)
231 if(SCI0CR2
& SCICR2_RX_ENABLE
){
237 if(SCI0CR2
& SCICR2_RX_ISR_ENABLE
){
243 // PWM experimentation