FreeEMS  0.2.0-SNAPSHOT-282-g9efc524
R18A1-13CrankWith5Cam.c
Go to the documentation of this file.
1 /* FreeEMS - the open source engine management system
2  *
3  * Copyright 2013-2014 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  * Decoder for the Honda R18A1 I4 engine.
33  *
34  * http://pastebin.com/QMdhE55v
35  */
36 
37 
38 #define DECODER_MAX_CODE_TIME 150
39 #define NUMBER_OF_REAL_EVENTS 26 // 12+1 Mostly Even Crank teeth, twice
40 #define NUMBER_OF_VIRTUAL_EVENTS 26 // Ditto.
41 #define DECODER_IMPLEMENTATION_C
42 
43 #include "../inc/freeEMS.h"
44 #include "../inc/utils.h"
45 #include "../inc/interrupts.h"
46 #include "../inc/decoderInterface.h"
47 
48 unsigned char camTeethSeen = 0;
49 unsigned char previousCrankTeethSeen = 0;
50 unsigned char crankTeethSinceLastCamTooth = 0;
51 
52 #define FIRST_GAP ANGLE(10) // With the 20 degree balance of the 30 degree segment following
53 
54 #define E0 ANGLE( 0)
55 #define E1 ANGLE( 30)
56 #define E2 ANGLE( 60)
57 #define E3 ANGLE( 90)
58 #define E4 ANGLE(120)
59 #define E5 ANGLE(150)
60 #define E6 ANGLE(180)
61 #define E7 ANGLE(210)
62 #define E8 ANGLE(240)
63 #define E9 ANGLE(270)
64 #define E10 ANGLE(300)
65 #define E11 ANGLE(330)
66 #define E12 (E11 + FIRST_GAP)
67 #define E13 ANGLE(360)
68 #define E14 ANGLE(390)
69 #define E15 ANGLE(420)
70 #define E16 ANGLE(450)
71 #define E17 ANGLE(480)
72 #define E18 ANGLE(510)
73 #define E19 ANGLE(540)
74 #define E20 ANGLE(570)
75 #define E21 ANGLE(600)
76 #define E22 ANGLE(630)
77 #define E23 ANGLE(660)
78 #define E24 ANGLE(690)
79 #define E25 (E24 + FIRST_GAP)
80 
81 // 3 >> 16
82 // 10 >> 23
83 // Note, if used in 360 degree crank only mode, the upper 13 values are simply ignored.
84 
85 CASSERT(E12 > E11, MID_ANGLE_LOWER)
86 CASSERT(E12 < E13, MID_ANGLE_UPPER)
87 CASSERT(E25 > E24, FINAL_ANGLE_LOWER)
88 CASSERT(E25 < ANGLE(720), FINAL_ANGLE_UPPER)
89 
90 const unsigned short eventAngles[] = {E0, E1, E2, E3, E4, E5, E6, E7, E8, E9, E10, E11, E12, E13, E14, E15, E16, E17, E18, E19, E20, E21, E22, E23, E24, E25};
91 const unsigned char eventValidForCrankSync[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
92 
94  // Set PT0 and PT1 to only capture on rising edges
95  TCTL4 = 0x05;
96 }
97 
99  camTeethSeen = 0;
102 
103  // Re-enable secondary interrupt so we can sync again!
104  TCTL4 |= BIT2;
105 }
106 
107 // Just count and check time stamps, sync is handled by the secondary ISR
109  /* Clear the interrupt flag for this input compare channel */
110  TFLG = 0x01;
112 
113  /* Save all relevant available data here */
114  unsigned short edgeTimeStamp = TC0; /* Save the edge time stamp */
115  unsigned char PTITCurrentState = PTIT; /* Save the values on port T regardless of the state of DDRT */
116 
117  // Prevent main from clearing values before sync is obtained!
119 
121 
123  /* Install the low word */
124  timeStamp.timeShorts[1] = edgeTimeStamp;
125  /* Find out what our timer value means and put it in the high word */
126  if(TFLGOF && !(edgeTimeStamp & 0x8000)){ /* see 10.3.5 paragraph 4 of 68hc11 ref manual for details */
127  timeStamp.timeShorts[0] = timerExtensionClock + 1;
128  }else{
129  timeStamp.timeShorts[0] = timerExtensionClock;
130  }
131  unsigned long thisEventTimeStamp = timeStamp.timeLong;
132 
133  unsigned long thisInterEventPeriod = 0;
135  thisInterEventPeriod = thisEventTimeStamp - lastPrimaryEventTimeStamp;
136  KeyUserDebugs.zsp7 = (unsigned short)thisInterEventPeriod; // Could truncate if under ~100rpm TODO DEBUG REMOVE
137  }
138 
139  unsigned short thisTicksPerDegree = 0;
141 
142  unsigned char lastEvent = KeyUserDebugs.currentEvent;
146  }
147 
148  unsigned short thisAngle = 0;
149  if(KeyUserDebugs.currentEvent == 0){
150  thisAngle = eventAngles[KeyUserDebugs.currentEvent] + totalEventAngleRange - eventAngles[lastEvent] ; // Optimisable... leave readable for now! :-p J/K learn from this...
151  }else{
152  thisAngle = eventAngles[KeyUserDebugs.currentEvent] - eventAngles[lastEvent];
153  }
154 
155  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
156 
158  unsigned short ratioBetweenThisAndLast = (unsigned short)(((unsigned long)lastPrimaryTicksPerDegree * 1000) / thisTicksPerDegree);
159  KeyUserDebugs.inputEventTimeTolerance = ratioBetweenThisAndLast;
162  return;
163  }else if(ratioBetweenThisAndLast < fixedConfigs2.decoderSettings.accelerationInputEventTimeTolerance){
165  return;
166  }else{
167  if(PTITCurrentState & 0x02){
168  // TODO Calculate RPM from last primaryLeadingEdgeTimeStamp
169  }else{
170  // TODO Calculate RPM from last primaryTrailingEdgeTimeStamp
171  }
172  }
173  }
174 
176  lastPrimaryTicksPerDegree = thisTicksPerDegree;
178  }
179 
180  /*else*/ if(KeyUserDebugs.decoderFlags & LAST_TIMESTAMP_VALID){ // TODO temp for testing just do rpm this way, fill above out later.
181  *ticksPerDegreeRecord = thisTicksPerDegree;
184 
185  // Set flag to say calc required
187 
188  // Reset the clock for reading timeout
190  }
191 
192  SCHEDULE_ECT_OUTPUTS();
193 
194  OUTPUT_COARSE_BBS();
195  }
196 
197  // Always
198  lastPrimaryEventTimeStamp = thisEventTimeStamp;
200 
202 }
203 
204 // CAM sensor doesn't use time stamps due to timing belt tension vibration, plus the crank has 6 times more events, so any discrepancy would be caught that way
206  /* Clear the interrupt flag for this input compare channel */
207  TFLG = 0x02;
210  if(camTeethSeen == 0){
211  camTeethSeen = 1;
213  }else{
216 
220  }else if(crankTeethSinceLastCamTooth == 1){
223  }else if(crankTeethSinceLastCamTooth != 6){
226  }else if(crankTeethSinceLastCamTooth < 6){
228  }else if(!crankTeethSinceLastCamTooth){ // Should never be zero :-p
230  }else{
232  }
233  return;
234  } // else is 6, just ignore.
235 
236  // Disable the interrupt for this ISR
238  TCTL4 &= NBIT2;
239  }
240  }
241 
243 }