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! */
24 /* This code is identical between all 6 channels, and thus we only want one copy of it. The X in each macro will be replaced with the real deal appropriate for the channel it is used for at the time. */
26 /* Each channel performs the following actions
28 * 1 Clear its interrupt flag
29 * 2 Record its start time
30 * 3 Measure and record its latency
31 * 4 Check to see if its just turned on
32 * 4.1 Copy the channels pulse width to a local variable
33 * 4.2 Determine the minimum pulse width based on code run time const and latency
34 * 4.3 Clamp used pulsewidth inside min and max
35 * 4.4 If used pulse width is larger than the current period of the engines cycle flag as always on
36 * 4.5 Set the action to turn off
37 * 4.6 Increment the time by pulse width
38 * 4.7 If staging required, either, switch them on and sched to turn off, or sched to turn on
39 * 5 Else it has just turned off
40 * 5.1 If staged channel is still on, turn it off
41 * 5.2 If(self schedule flagged) schedule the next start
42 * 5.3 Else disable itself
43 * 6 Calculate and record code run time
48 /* Clear the interrupt flag for this channel */
49 TFLG
= injectorMainOnMasks
[INJECTOR_CHANNEL_NUMBER
];
51 /* Record the current time as start time */
52 unsigned short TCNTStart
= TCNT
;
54 /* Record the edge time stamp from the IC register */
55 unsigned short edgeTimeStamp
= *injectorMainTimeRegisters
[INJECTOR_CHANNEL_NUMBER
];
57 /* Calculate and store the latency based on compare time and start time */
58 injectorCodeLatencies
[INJECTOR_CHANNEL_NUMBER
] = TCNTStart
- edgeTimeStamp
;
60 /* If rising edge triggered this */
61 if(PTIT
& injectorMainOnMasks
[INJECTOR_CHANNEL_NUMBER
]){ // Stuff for switch on time
63 /* Find out what max and min for pulse width are */
64 unsigned short localPulseWidth
= injectorMainPulseWidthsRealtime
[INJECTOR_CHANNEL_NUMBER
];
65 unsigned short localMinimumPulseWidth
= injectorSwitchOnCodeTime
+ injectorCodeLatencies
[INJECTOR_CHANNEL_NUMBER
];
67 /* TODO *maybe* instead of checking min and increasing pulse, just force it straight off if diff between start and now+const is greater than desired pulsewidth */
69 /* Ensure we dont go under minimum pulsewidth */
70 if(localPulseWidth
< localMinimumPulseWidth
){
71 localPulseWidth
= localMinimumPulseWidth
;
72 }/* else{ just use the value } */
76 /* Install the low word */
77 timeStamp
.timeShorts
[1] = edgeTimeStamp
;
78 /* Find out what our timer value means and put it in the high word */
79 if(TFLGOF
&& !(edgeTimeStamp
& 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
80 timeStamp
.timeShorts
[0] = timerExtensionClock
+ 1;
82 timeStamp
.timeShorts
[0] = timerExtensionClock
;
85 // store the end time for use in the scheduler
86 injectorMainEndTimes
[INJECTOR_CHANNEL_NUMBER
] = timeStamp
.timeLong
+ localPulseWidth
;
88 /* Set the action for compare to switch off FIRST or it might inadvertently PWM the injector during opening... */
89 *injectorMainControlRegisters
[INJECTOR_CHANNEL_NUMBER
] &= injectorMainGoLowMasks
[INJECTOR_CHANNEL_NUMBER
];
91 /* Set the time to turn off again */
92 *injectorMainTimeRegisters
[INJECTOR_CHANNEL_NUMBER
] += localPulseWidth
;
94 /* This is the point we actually want the time to, but because the code is so simple, it can't help but be a nice short time */
96 /* If staged injection is required, switch on or schedule corresponding staged injector and remember that we did. */
97 if(coreStatusA
& STAGED_REQUIRED
){
98 if(fixedConfigs1
.coreSettingsA
& STAGED_START
){
99 /* Switch that channel on NOW */
100 STAGEDPORT
|= STAGEDXON
;
101 stagedOn
|= STAGEDXON
;
103 /* Schedule the start at a later time */
104 // TODO PIT scheduling of staged start
107 /* Calculate and store code run time */
108 injectorCodeOpenRuntimes
[INJECTOR_CHANNEL_NUMBER
] = TCNT
- TCNTStart
;
109 }else{ // Stuff for switch off time
110 /* If we switched the staged injector on and it's still on, turn it off now. */
111 if(stagedOn
& STAGEDXON
){
112 STAGEDPORT
&= STAGEDXOFF
;
113 stagedOn
&= STAGEDXOFF
;
116 /* Set the action for compare to switch on and the time to next start time, clear the self timer flag */
117 if(selfSetTimer
& injectorMainOnMasks
[INJECTOR_CHANNEL_NUMBER
]){
118 *injectorMainTimeRegisters
[INJECTOR_CHANNEL_NUMBER
] = injectorMainStartTimesHolding
[INJECTOR_CHANNEL_NUMBER
];
119 *injectorMainControlRegisters
[INJECTOR_CHANNEL_NUMBER
] |= injectorMainGoHighMasks
[INJECTOR_CHANNEL_NUMBER
];
120 selfSetTimer
&= injectorMainOffMasks
[INJECTOR_CHANNEL_NUMBER
];
122 // Disable interrupts and actions incase the period from this end to the next start is long (saves cpu)
123 TIE
&= injectorMainOffMasks
[INJECTOR_CHANNEL_NUMBER
];
124 *injectorMainControlRegisters
[INJECTOR_CHANNEL_NUMBER
] &= injectorMainDisableMasks
[INJECTOR_CHANNEL_NUMBER
];
126 /* Calculate and store code run time */
127 injectorCodeCloseRuntimes
[INJECTOR_CHANNEL_NUMBER
] = TCNT
- TCNTStart
;