1 /* FreeEMS - the open source engine management system
3 * Copyright 2011-2013 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!
27 #define DECODER_IMPLEMENTATION_C
29 #include "inc/MitsiAndMazda-CAS-4and1.h"
31 void decoderInitPreliminary(){} // This decoder works with the defaults
32 void perDecoderReset(){
33 unknownLeadingEdges
= 0;
39 * @ingroup interruptHandlers
40 * @ingroup enginePositionRPMDecoders
42 * @brief Reads Mitsi 4 and 1 CAS units
44 * Two interrupts share state and cross communicate to
45 * find and maintain sync and position information.
47 * Development thread: http://forum.diyefi.org/viewtopic.php?f=56&t=1078
52 /* Clear the interrupt flag for this input compare channel */
54 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT0
, PORTB
);
56 /* Save all relevant available data here */
57 edgeTimeStamp
= TC0
; /* Save the edge time stamp */
58 unsigned char PTITCurrentState
= PTIT
; /* Save the values on port T regardless of the state of DDRT */
60 KeyUserDebugs
.primaryTeethSeen
++;
62 /* Install the low word */
63 timeStamp
.timeShorts
[1] = edgeTimeStamp
;
64 /* Find out what our timer value means and put it in the high word */
65 if(TFLGOF
&& !(edgeTimeStamp
& 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
66 timeStamp
.timeShorts
[0] = timerExtensionClock
+ 1;
68 timeStamp
.timeShorts
[0] = timerExtensionClock
;
70 unsigned long thisEventTimeStamp
= timeStamp
.timeLong
;
72 unsigned long thisInterEventPeriod
= 0;
73 if(KeyUserDebugs
.decoderFlags
& LAST_TIMESTAMP_VALID
){
74 thisInterEventPeriod
= thisEventTimeStamp
- lastEventTimeStamp
;
77 // Pins 0, 2, 4 and 7 - no need to check for numbers, just always do on rising edge and only in primary isr
78 // Always sample in this ISR
79 sampleEachADC(ADCBuffers
);
80 Counters
.syncedADCreadings
++;
82 // Set flag to say calc required
83 coreStatusA
|= CALC_FUEL_IGN
;
85 // Reset the clock for reading timeout
86 Clocks
.timeoutADCreadingClock
= 0;
88 // Determine the correct event based on post transition state
89 unsigned char correctEvent
= 0;
90 if(PTITCurrentState
& 0x01){
91 if(!(PTITCurrentState
& 0x02)){
95 if(PTITCurrentState
& 0x02){
96 unknownLeadingEdges
++;
97 if(unknownLeadingEdges
== 3){
102 unknownLeadingEdges
= 0;
106 unsigned char lastEvent
= 0;
107 if(KeyUserDebugs
.decoderFlags
& CAM_SYNC
){
108 lastEvent
= KeyUserDebugs
.currentEvent
;
109 KeyUserDebugs
.currentEvent
++;
110 if(KeyUserDebugs
.currentEvent
== numberOfRealEvents
){
111 KeyUserDebugs
.currentEvent
= 0;
114 // ...and, if known, check that it's correct
115 if(correctEvent
!= 0){
116 if(KeyUserDebugs
.currentEvent
!= correctEvent
){
117 resetToNonRunningState(STATE_MISMATCH_IN_PRIMARY_RPM_ISR
);
119 }else if(!(KeyUserDebugs
.decoderFlags
& OK_TO_SCHEDULE
)){
120 SET_SYNC_LEVEL_TO(CAM_SYNC
);
121 } // Else do nothing, we're running!
123 }else if(correctEvent
!= 0){
124 KeyUserDebugs
.currentEvent
= correctEvent
;
125 lastEvent
= KeyUserDebugs
.currentEvent
- 1;
126 SET_SYNC_LEVEL_TO(CAM_SYNC
);
129 unsigned short thisTicksPerDegree
= 0;
130 if(KeyUserDebugs
.decoderFlags
& CAM_SYNC
){
131 unsigned short thisAngle
= 0;
132 if(KeyUserDebugs
.currentEvent
== 0){
133 thisAngle
= eventAngles
[KeyUserDebugs
.currentEvent
] + totalEventAngleRange
- eventAngles
[lastEvent
] ; // Optimisable... leave readable for now! :-p J/K learn from this...
135 thisAngle
= eventAngles
[KeyUserDebugs
.currentEvent
] - eventAngles
[lastEvent
];
138 thisTicksPerDegree
= (unsigned short)((ticks_per_degree_multiplier
* thisInterEventPeriod
) / thisAngle
); // with current scale range for 60/12000rpm is largest ticks per degree = 3472, smallest = 17 with largish error
140 if(KeyUserDebugs
.decoderFlags
& LAST_PERIOD_VALID
){
141 unsigned short ratioBetweenThisAndLast
= (unsigned short)(((unsigned long)lastTicksPerDegree
* 1000) / thisTicksPerDegree
);
142 KeyUserDebugs
.inputEventTimeTolerance
= ratioBetweenThisAndLast
;
143 if(ratioBetweenThisAndLast
> fixedConfigs2
.decoderSettings
.decelerationInputEventTimeTolerance
){
144 resetToNonRunningState(PRIMARY_EVENT_ARRIVED_TOO_LATE
);
146 }else if(ratioBetweenThisAndLast
< fixedConfigs2
.decoderSettings
.accelerationInputEventTimeTolerance
){
147 resetToNonRunningState(PRIMARY_EVENT_ARRIVED_TOO_EARLY
);
150 if(PTITCurrentState
& 0x01){
151 // TODO Calculate RPM from last primaryLeadingEdgeTimeStamp
153 // TODO Calculate RPM from last primaryTrailingEdgeTimeStamp
156 }/*else*/ if(KeyUserDebugs
.decoderFlags
& LAST_TIMESTAMP_VALID
){ // TODO temp for testing just do rpm this way, fill above out later.
157 *ticksPerDegreeRecord
= thisTicksPerDegree
;
161 SCHEDULE_ECT_OUTPUTS();
165 if(KeyUserDebugs
.decoderFlags
& LAST_TIMESTAMP_VALID
){
166 lastTicksPerDegree
= thisTicksPerDegree
;
167 KeyUserDebugs
.decoderFlags
|= LAST_PERIOD_VALID
;
170 lastEventTimeStamp
= thisEventTimeStamp
;
171 KeyUserDebugs
.decoderFlags
|= LAST_TIMESTAMP_VALID
;
173 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT0
, PORTB
);
177 void SecondaryRPMISR(){
178 // Reads the inner slot on the disk.
180 /* Clear the interrupt flag for this input compare channel */
182 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT1
, PORTB
);
184 /* Save all relevant available data here */
185 edgeTimeStamp
= TC1
; /* Save the timestamp */
186 unsigned char PTITCurrentState
= PTIT
; /* Save the values on port T regardless of the state of DDRT */
188 KeyUserDebugs
.secondaryTeethSeen
++;
189 // remember that this is both edges, though... 8 per cycle, 4 per rev for the outter wheel, 2/1 for this wheel.
191 /* Install the low word */
192 timeStamp
.timeShorts
[1] = edgeTimeStamp
;
193 /* Find out what our timer value means and put it in the high word */
194 if(TFLGOF
&& !(edgeTimeStamp
& 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
195 timeStamp
.timeShorts
[0] = timerExtensionClock
+ 1;
197 timeStamp
.timeShorts
[0] = timerExtensionClock
;
199 unsigned long thisEventTimeStamp
= timeStamp
.timeLong
;
201 unsigned long thisInterEventPeriod
= 0;
202 if(KeyUserDebugs
.decoderFlags
& LAST_TIMESTAMP_VALID
){
203 thisInterEventPeriod
= thisEventTimeStamp
- lastEventTimeStamp
;
206 // Determine the correct event based on post transition state (and toggle debug pins)
207 unsigned char correctEvent
;
208 if(PTITCurrentState
& 0x02){
214 // Only sample if not synced, cleans up readings.
215 if(!(KeyUserDebugs
.decoderFlags
& CAM_SYNC
)){
216 sampleEachADC(ADCBuffers
);
217 Counters
.syncedADCreadings
++;
219 // Set flag to say calc required
220 coreStatusA
|= CALC_FUEL_IGN
;
222 // Reset the clock for reading timeout
223 Clocks
.timeoutADCreadingClock
= 0;
226 unsigned char lastEvent
= 0;
227 if(KeyUserDebugs
.decoderFlags
& CAM_SYNC
){
228 lastEvent
= KeyUserDebugs
.currentEvent
;
229 KeyUserDebugs
.currentEvent
++;
231 // ...and check that it's correct
232 if(KeyUserDebugs
.currentEvent
!= correctEvent
){
233 resetToNonRunningState(STATE_MISMATCH_IN_SECONDARY_RPM_ISR
);
235 }else if(!(KeyUserDebugs
.decoderFlags
& OK_TO_SCHEDULE
)){
236 SET_SYNC_LEVEL_TO(CAM_SYNC
);
237 } // Else do nothing, we're running!
238 }else{ // If not synced, sync, as in this ISR we always know where we are.
239 KeyUserDebugs
.currentEvent
= correctEvent
;
240 lastEvent
= KeyUserDebugs
.currentEvent
- 1;
241 SET_SYNC_LEVEL_TO(CAM_SYNC
);
244 unsigned short thisTicksPerDegree
= 0;
245 if(KeyUserDebugs
.decoderFlags
& CAM_SYNC
){
246 unsigned short thisAngle
= eventAngles
[KeyUserDebugs
.currentEvent
] - eventAngles
[lastEvent
];
248 thisTicksPerDegree
= (unsigned short)((ticks_per_degree_multiplier
* thisInterEventPeriod
) / thisAngle
); // with current scale range for 60/12000rpm is largest ticks per degree = 3472, smallest = 17 with largish error
250 if(KeyUserDebugs
.decoderFlags
& LAST_PERIOD_VALID
){
251 unsigned short ratioBetweenThisAndLast
= (unsigned short)(((unsigned long)lastTicksPerDegree
* 1000) / thisTicksPerDegree
);
252 KeyUserDebugs
.inputEventTimeTolerance
= ratioBetweenThisAndLast
;
253 if(ratioBetweenThisAndLast
> fixedConfigs2
.decoderSettings
.decelerationInputEventTimeTolerance
){
254 resetToNonRunningState(SECONDARY_EVENT_ARRIVED_TOO_LATE
);
256 }else if(ratioBetweenThisAndLast
< fixedConfigs2
.decoderSettings
.accelerationInputEventTimeTolerance
){
257 resetToNonRunningState(SECONDARY_EVENT_ARRIVED_TOO_EARLY
);
260 }/*else*/ if(KeyUserDebugs
.decoderFlags
& LAST_TIMESTAMP_VALID
){
261 *ticksPerDegreeRecord
= thisTicksPerDegree
;
265 SCHEDULE_ECT_OUTPUTS();
269 if(KeyUserDebugs
.decoderFlags
& LAST_TIMESTAMP_VALID
){
270 lastTicksPerDegree
= thisTicksPerDegree
;
271 KeyUserDebugs
.decoderFlags
|= LAST_PERIOD_VALID
;
274 lastEventTimeStamp
= thisEventTimeStamp
;
275 KeyUserDebugs
.decoderFlags
|= LAST_TIMESTAMP_VALID
;
277 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT1
, PORTB
);