FreeEMS  0.2.0-SNAPSHOT-285-g028e24c
EvenTeeth-Xand1.c
Go to the documentation of this file.
1 /* FreeEMS - the open source engine management system
2  *
3  * Copyright 2011-2013 Fred Cooke
4  *
5  * This file is part of the FreeEMS project.
6  *
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.
11  *
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.
16  *
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/
19  *
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!
22  *
23  * Thank you for choosing FreeEMS to run your engine!
24  */
25 
26 
27 /** @file
28  *
29  * @ingroup interruptHandlers
30  * @ingroup enginePositionRPMDecoders
31  *
32  * @brief For evenly spaced teeth on the cam or crank with a single second input.
33  *
34  * Fill out a data reverse header and include this file. Sync is provided by the
35  * second input allowing a sequential and/or COP/CNP setup to be used.
36  *
37  * VR edition with only one edge used!
38  */
39 
40 
42  // Set PT0 and PT1 to only capture on rising
43  TCTL4 = 0x05; // 0000 0101 Capture rising edges only on PT0&1
44 }
45 
46 void perDecoderReset(){} // Nothing special to reset for this code
47 
48 
50  /* Clear the interrupt flag for this input compare channel */
51  TFLG = 0x01;
53 
54  /* Save all relevant available data here */
55  unsigned short edgeTimeStamp = TC0; /* Save the edge time stamp */
56  unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */
57 
58  // Prevent main from clearing values before sync is obtained!
60 
62 
64  /* Install the low word */
65  timeStamp.timeShorts[1] = edgeTimeStamp;
66  /* Find out what our timer value means and put it in the high word */
67  if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
68  timeStamp.timeShorts[0] = timerExtensionClock + 1;
69  }else{
70  timeStamp.timeShorts[0] = timerExtensionClock;
71  }
72  unsigned long thisEventTimeStamp = timeStamp.timeLong;
73 
74  unsigned long thisInterEventPeriod = 0;
75  unsigned short thisTicksPerDegree = 0;
77  thisInterEventPeriod = thisEventTimeStamp - lastPrimaryEventTimeStamp;
78  thisTicksPerDegree = (unsigned short)((ticks_per_degree_multiplier * thisInterEventPeriod) / eventAngles[1]); // with current scale range for 60/12000rpm is largest ticks per degree = 3472, smallest = 17 with largish error
79  }
80 
81  if(KeyUserDebugs.decoderFlags & CONFIGURED_SYNC){
85  return;
86  }// Can never be greater than without a code error or genuine noise issue, so give it a miss as we can not guarantee where we are now.
87 
89  unsigned short ratioBetweenThisAndLast = (unsigned short)(((unsigned long)lastPrimaryTicksPerDegree * 1000) / thisTicksPerDegree);
90  KeyUserDebugs.inputEventTimeTolerance = ratioBetweenThisAndLast;
93  return;
94  }else if(ratioBetweenThisAndLast < fixedConfigs2.decoderSettings.accelerationInputEventTimeTolerance){
96  return;
97  }else{
98  if(PTITCurrentState & 0x01){
99  // TODO Calculate RPM from last primaryLeadingEdgeTimeStamp
100  }else{
101  // TODO Calculate RPM from last primaryTrailingEdgeTimeStamp
102  }
103  }
104  }/*else*/ if(KeyUserDebugs.decoderFlags & LAST_TIMESTAMP_VALID){ // TODO temp for testing just do rpm this way, fill above out later.
105  *ticksPerDegreeRecord = thisTicksPerDegree;
108 
109  // Set flag to say calc required
111 
112  // Reset the clock for reading timeout
114  }
115 
116  // for now, sample always and see what we get result wise...
117 // if((currentEvent % 6) == 0){
118 // sampleEachADC(ADCBuffers);
119 // Counters.syncedADCreadings++;
120 //
121 // // Set flag to say calc required
122 // coreStatusA |= CALC_FUEL_IGN;
123 //
124 // // Reset the clock for reading timeout
125 // Clocks.timeoutADCreadingClock = 0;
126 // }
127 
128  SCHEDULE_ECT_OUTPUTS();
129  }
130 
131  OUTPUT_COARSE_BBS();
132 
133  // do these always at first, and use them with a single 30 degree angle for the first cut
135  lastPrimaryTicksPerDegree = thisTicksPerDegree;
137  }
138  // Always
139  lastPrimaryEventTimeStamp = thisEventTimeStamp;
141 
143 }
144 
145 
147  /* Clear the interrupt flag for this input compare channel */
148  TFLG = 0x02;
150 
151  /* Save all relevant available data here */
152  unsigned short edgeTimeStamp = TC1; /* Save the timestamp */
153 // unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */
154 
156 
158  /* Install the low word */
159  timeStamp.timeShorts[1] = edgeTimeStamp;
160  /* Find out what our timer value means and put it in the high word */
161  if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
162  timeStamp.timeShorts[0] = timerExtensionClock + 1;
163  }else{
164  timeStamp.timeShorts[0] = timerExtensionClock;
165  }
166  unsigned long thisEventTimeStamp = timeStamp.timeLong;
167 
168  unsigned long thisInterEventPeriod = 0;
170  thisInterEventPeriod = thisEventTimeStamp - lastSecondaryEventTimeStamp;
171  }
172 
173  // This sets currentEvent to 255 such that when the primary ISR runs it is rolled over to zero!
174  if(KeyUserDebugs.decoderFlags & CONFIGURED_SYNC){
175  // If sync not confirmed, register sync point. Must be before the count checks, otherwise loss of sync would result in sync being redeclared.
177  SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
178  }
179 
180  /* If the count is less than 23, then we know that the electrical pulse that triggered
181  * this ISR execution was almost certainly in error and it is NOT valid to stay in sync.
182  *
183  * If the count is greater than 24, then we know that an electrical noise pulse triggered
184  * the other interrupt in between and was missed by the time period checks (unlikely, but
185  * possible) and that, therefore, there could have been a noise pulse on this input too,
186  * and therefore we don't really know where we are.
187  *
188  * In the case where the count is exactly 24 we can only rely on the time period checks in
189  * the other ISR, which should be sufficient unless poorly setup by a user with too wide
190  * of a tolerance level.
191  *
192  * There is zero point adding relative timing checks to this ISR because by nature, the
193  * other N teeth have already checked out good timing wise and therefore the average also
194  * does. Thus if we did check, for it to ever fail it would need to be tighter, and in
195  * reality it must be more loose due to the larger possible variation over the much much
196  * larger time frame.
197  */
202  } // ELSE do nothing, and be happy :-)
203  }else{ // If sync not found, register first sync point, as this is our reference point.
204  SET_SYNC_LEVEL_TO(CONFIGURED_SYNC);
205  }
206 
207  KeyUserDebugs.currentEvent = 0xFF; // TODO reset always, and catch noise induced errors below, this behaviour (now some lines above) may be bad/not fussy enough, or could be good, depending upon determinate nature of the inter event timing between primary and secondary, or not, perhaps move "lose sync or correct sync" as a configuration variable
208 
210 }