FreeEMS  0.2.0-SNAPSHOT-285-g028e24c
HallOrOptical-Distributor-XofY.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 Echos the input on the first ignition output
33  *
34  * This decoder is for any 4 tooth/slot hall or optical cam speed sensor and to
35  * be used for distributor and/or 4 shot batch injection only.
36  *
37  * To build a version of this decoder with a specific angle pair for your hall
38  * or optical distributor, just define the DECODER_IMPLEMENTATION_C flag,
39  * include the four required headers, define the angle for E1, and define the
40  * unique decoder name string!
41  *
42  * To effectively reverse the polarity, just subtract your angle from 180 and
43  * it will then be correct, assuming that either angle is correct.
44  */
45 
46 
47 #define angleOfSingleIteration (180 * ANGLE_FACTOR)
48 
49 #define E0 0
50 // Define E1 in your reverse header!
51 #define E2 (E0 + angleOfSingleIteration)
52 #define E3 (E1 + angleOfSingleIteration)
53 #define E4 (E0 + (2 * angleOfSingleIteration))
54 #define E5 (E1 + (2 * angleOfSingleIteration))
55 #define E6 (E0 + (3 * angleOfSingleIteration))
56 #define E7 (E1 + (3 * angleOfSingleIteration))
57 
58 
59 #if (E1 >= angleOfSingleIteration)
60 #error "Angle E1 defined to be larger than the available angle which it is within!"
61 #endif
62 
63 
64 const unsigned short eventAngles[] = {E0, E1, E2, E3, E4, E5, E6, E7};
65 const unsigned char eventValidForCrankSync[] = {0,0,0,0,0,0,0,0}; // Unused in this decoder.
66 
67 
69  TCTL4 = 0x03; /* Capture on both edges of T0 only, capture off for 1,2,3 */
70 } // This decoder works with the defaults
71 void perDecoderReset(){} // Nothing special to reset for this code
72 
73 
75  /* Clear the interrupt flag for this input compare channel */
76  TFLG = 0x01;
78 
79  /* Save all relevant available data here */
80  unsigned short edgeTimeStamp = TC0; /* Save the edge time stamp */
81  unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */
82 
84 
86 
87  /* Install the low word */
88  timeStamp.timeShorts[1] = edgeTimeStamp;
89  /* Find out what our timer value means and put it in the high word */
90  if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
91  timeStamp.timeShorts[0] = timerExtensionClock + 1;
92  }else{
93  timeStamp.timeShorts[0] = timerExtensionClock;
94  }
95  unsigned long thisEventTimeStamp = timeStamp.timeLong;
96 
97  unsigned char lastEvent = 0;
98  unsigned short thisTicksPerDegree = 0;
99  if(PTITCurrentState & 0x01){
100  // temporary data from inputs
101  unsigned long primaryLeadingEdgeTimeStamp = timeStamp.timeLong;
102  unsigned long timeBetweenSuccessivePrimaryPulses = primaryLeadingEdgeTimeStamp - lastPrimaryEventTimeStamp;
103  lastPrimaryEventTimeStamp = primaryLeadingEdgeTimeStamp;
104 
105 
106  thisTicksPerDegree = (unsigned short)((ticks_per_degree_multiplier * timeBetweenSuccessivePrimaryPulses) / angleOfSingleIteration);
107  *ticksPerDegreeRecord = thisTicksPerDegree;
108 
109  // TODO Once sampling/RPM is configurable, use this tooth for a lower MAP reading.
112 
113  /* Set flag to say calc required */
115 
116  /* Reset the clock for reading timeout */
118 
120  lastEvent = 0;
121  }else{
122  // temporary data from inputs
123  unsigned long secondaryLeadingEdgeTimeStamp = timeStamp.timeLong;
124  unsigned long timeBetweenSuccessiveSecondaryPulses = secondaryLeadingEdgeTimeStamp - lastSecondaryEventTimeStamp;
125  lastSecondaryEventTimeStamp = secondaryLeadingEdgeTimeStamp;
126 
127 
128  thisTicksPerDegree = (unsigned short)((ticks_per_degree_multiplier * timeBetweenSuccessiveSecondaryPulses) / angleOfSingleIteration);
129  *ticksPerDegreeRecord = thisTicksPerDegree;
130 
131  // TODO make this stuff behave correctly, this one will only run at startup, and the other will always run, but do it by generic config and split this stuff out into a shared function, soon.
134 
135  /* Set flag to say calc required */
137 
138  /* Reset the clock for reading timeout */
140 
142  lastEvent = 1;
143  }
144 
145  unsigned long thisInterEventPeriod = 0;
147  thisInterEventPeriod = thisEventTimeStamp - lastEventTimeStamp;
148  }
149 
150  // This should check during gain of sync too and prevent gaining sync if the numbers aren't right, however this is a step up for the Hotel at this time.
152  unsigned short thisAngle = 0;
153  if(KeyUserDebugs.currentEvent == 0){
154  // Fix this to work for all:
155 // thisAngle = eventAngles[KeyUserDebugs.currentEvent] + totalEventAngleRange - eventAngles[lastEvent] ; // Optimisable... leave readable for now! :-p J/K learn from this...
156  thisAngle = eventAngles[KeyUserDebugs.currentEvent] + angleOfSingleIteration - eventAngles[lastEvent] ; // Optimisable... leave readable for now! :-p J/K learn from this...
157  }else{
158  thisAngle = eventAngles[KeyUserDebugs.currentEvent] - eventAngles[lastEvent];
159  }
160 
161  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
162 
164  unsigned short ratioBetweenThisAndLast = (unsigned short)(((unsigned long)lastTicksPerDegree * 1000) / thisTicksPerDegree);
165  KeyUserDebugs.inputEventTimeTolerance = ratioBetweenThisAndLast;
168  return;
169  }else if(ratioBetweenThisAndLast < fixedConfigs2.decoderSettings.accelerationInputEventTimeTolerance){
171  return;
172  }
173  }
174  }
175 
176  SCHEDULE_ECT_OUTPUTS();
177 
178  OUTPUT_COARSE_BBS();
179 
180  /* TODO this delays outputs until the fourth ISR execution, but we could
181  * get them one execution or 1/8 of a rev sooner if we did a preliminary
182  * calc from the previous edge instead of the previous same edge now, and
183  *
184  * The proper way to do this is set sync when we have it and not set data
185  * as having been recorded until we know the data is good. That way the
186  * scheduler can keep things unscheduled until the time is right.
187  */
190  }
191 
193  lastTicksPerDegree = thisTicksPerDegree;
195  }
196  // Always
197  lastEventTimeStamp = thisEventTimeStamp;
199 
201 }
202 
203 
204 #include "../inc/defaultSecondaryRPMISR.c"