Clean up the ADC sampling in the 4and1 decoder by removing duplication. Rename a...
[freeems-vanilla.git] / src / main / decoders / MitsiAndMazda-CAS-4and1.c
bloba20a7d9a8aec66c6a5e30440975741bc335874ef
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;
37 /** @file
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
51 void PrimaryRPMISR(){
52 /* Clear the interrupt flag for this input compare channel */
53 TFLG = 0x01;
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;
67 }else{
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)){
92 correctEvent = 8;
94 }else{
95 if(PTITCurrentState & 0x02){
96 unknownLeadingEdges++;
97 if(unknownLeadingEdges == 3){
98 correctEvent = 4;
100 }else{
101 correctEvent = 7;
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);
118 return;
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...
134 }else{
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);
145 return;
146 }else if(ratioBetweenThisAndLast < fixedConfigs2.decoderSettings.accelerationInputEventTimeTolerance){
147 resetToNonRunningState(PRIMARY_EVENT_ARRIVED_TOO_EARLY);
148 return;
149 }else{
150 if(PTITCurrentState & 0x01){
151 // TODO Calculate RPM from last primaryLeadingEdgeTimeStamp
152 }else{
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();
163 OUTPUT_COARSE_BBS();
165 if(KeyUserDebugs.decoderFlags & LAST_TIMESTAMP_VALID){
166 lastTicksPerDegree = thisTicksPerDegree;
167 KeyUserDebugs.decoderFlags |= LAST_PERIOD_VALID;
169 // Always
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 */
181 TFLG = 0x02;
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;
196 }else{
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){
209 correctEvent = 9;
210 }else{
211 correctEvent = 6;
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);
234 return;
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);
255 return;
256 }else if(ratioBetweenThisAndLast < fixedConfigs2.decoderSettings.accelerationInputEventTimeTolerance){
257 resetToNonRunningState(SECONDARY_EVENT_ARRIVED_TOO_EARLY);
258 return;
260 }/*else*/ if(KeyUserDebugs.decoderFlags & LAST_TIMESTAMP_VALID){
261 *ticksPerDegreeRecord = thisTicksPerDegree;
265 SCHEDULE_ECT_OUTPUTS();
267 OUTPUT_COARSE_BBS();
269 if(KeyUserDebugs.decoderFlags & LAST_TIMESTAMP_VALID){
270 lastTicksPerDegree = thisTicksPerDegree;
271 KeyUserDebugs.decoderFlags |= LAST_PERIOD_VALID;
273 // Always
274 lastEventTimeStamp = thisEventTimeStamp;
275 KeyUserDebugs.decoderFlags |= LAST_TIMESTAMP_VALID;
277 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS, NBIT1, PORTB);