FreeEMS
0.2.0-SNAPSHOT-285-g028e24c
Main Page
Related Pages
Modules
Data Structures
Files
File List
Globals
src
main
decoders
JSeries-12CrankWith6-2Cam.c
Go to the documentation of this file.
1
/* FreeEMS - the open source engine management system
2
*
3
* Copyright 2012-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 J Series V6 engine, using one cam wheel and the crank wheel.
33
*
34
* @author Peter Johnson
35
*/
36
37
38
#define DECODER_MAX_CODE_TIME 150
39
#define NUMBER_OF_REAL_EVENTS 24 // 12 Even Crank teeth
40
#define NUMBER_OF_VIRTUAL_EVENTS 24 // 24 Crank teeth in 720degrees
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
const
unsigned
short
eventAngles
[] = {
ANGLE
( 0),
ANGLE
( 30),
ANGLE
( 60),
ANGLE
( 90),
53
ANGLE
(120),
ANGLE
(150),
ANGLE
(180),
ANGLE
(210),
54
ANGLE
(240),
ANGLE
(270),
ANGLE
(300),
ANGLE
(330),
55
ANGLE
(360),
ANGLE
(390),
ANGLE
(420),
ANGLE
(450),
56
ANGLE
(480),
ANGLE
(510),
ANGLE
(540),
ANGLE
(570),
57
ANGLE
(600),
ANGLE
(630),
ANGLE
(660),
ANGLE
(690)};
58
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};
59
60
void
decoderInitPreliminary
(){
61
// Set PT0 and PT1 to only capture on rising edges
62
TCTL4
= 0x05;
63
}
64
65
void
perDecoderReset
(){
66
camTeethSeen
= 0;
67
previousCrankTeethSeen
= 0;
68
crankTeethSinceLastCamTooth
= 0;
69
}
70
71
// Just count and check time stamps, sync is handled by the secondary ISR
72
void
PrimaryRPMISR
(){
73
/* Clear the interrupt flag for this input compare channel */
74
TFLG
= 0x01;
75
DEBUG_TURN_PIN_ON
(
DECODER_BENCHMARKS
,
BIT0
,
PORTB
);
76
77
/* Save all relevant available data here */
78
unsigned
short
edgeTimeStamp
=
TC0
;
/* Save the edge time stamp */
79
unsigned
char
PTITCurrentState =
PTIT
;
/* Save the values on port T regardless of the state of DDRT */
80
81
// Prevent main from clearing values before sync is obtained!
82
Clocks
.
timeoutADCreadingClock
= 0;
83
84
KeyUserDebugs
.
primaryTeethSeen
++;
85
86
LongTime
timeStamp
;
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
short
thisTicksPerDegree = 0;
98
if
(
KeyUserDebugs
.
decoderFlags
&
LAST_TIMESTAMP_VALID
){
99
unsigned
long
thisInterEventPeriod = thisEventTimeStamp -
lastPrimaryEventTimeStamp
;
100
thisTicksPerDegree = (
unsigned
short)((
ticks_per_degree_multiplier
* thisInterEventPeriod) /
eventAngles
[1]);
101
}
102
103
if
(
KeyUserDebugs
.
decoderFlags
&
CAM_SYNC
){
104
if
(
KeyUserDebugs
.
currentEvent
== 23){
105
KeyUserDebugs
.
currentEvent
= 0;
106
}
else
{
107
KeyUserDebugs
.
currentEvent
++;
108
}
109
if
(
KeyUserDebugs
.
currentEvent
==
numberOfRealEvents
){
110
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_HIGH_NOISE
);
111
return
;
112
}
// 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.
113
114
if
(
KeyUserDebugs
.
decoderFlags
&
LAST_PERIOD_VALID
){
115
unsigned
short
ratioBetweenThisAndLast = (
unsigned
short)(((
unsigned
long
)
lastPrimaryTicksPerDegree
* 1000) / thisTicksPerDegree);
116
KeyUserDebugs
.
inputEventTimeTolerance
= ratioBetweenThisAndLast;
117
if
(ratioBetweenThisAndLast >
fixedConfigs2
.
decoderSettings
.
decelerationInputEventTimeTolerance
){
118
resetToNonRunningState
(
PRIMARY_EVENT_ARRIVED_TOO_LATE
);
119
return
;
120
}
else
if
(ratioBetweenThisAndLast <
fixedConfigs2
.
decoderSettings
.
accelerationInputEventTimeTolerance
){
121
resetToNonRunningState
(
PRIMARY_EVENT_ARRIVED_TOO_EARLY
);
122
return
;
123
}
else
{
124
if
(PTITCurrentState & 0x02){
125
// TODO Calculate RPM from last primaryLeadingEdgeTimeStamp
126
}
else
{
127
// TODO Calculate RPM from last primaryTrailingEdgeTimeStamp
128
}
129
}
130
}
/*else*/
if
(
KeyUserDebugs
.
decoderFlags
&
LAST_TIMESTAMP_VALID
){
// TODO temp for testing just do rpm this way, fill above out later.
131
*
ticksPerDegreeRecord
= thisTicksPerDegree;
132
sampleEachADC
(
ADCBuffers
);
133
Counters
.
syncedADCreadings
++;
134
135
// Set flag to say calc required
136
coreStatusA
|=
CALC_FUEL_IGN
;
137
138
// Reset the clock for reading timeout
139
Clocks
.
timeoutADCreadingClock
= 0;
140
}
141
142
SCHEDULE_ECT_OUTPUTS();
143
}
144
145
OUTPUT_COARSE_BBS();
146
147
// do these always at first, and use them with a single 30 degree angle for the first cut
148
if
(
KeyUserDebugs
.
decoderFlags
&
LAST_TIMESTAMP_VALID
){
149
lastPrimaryTicksPerDegree
= thisTicksPerDegree;
150
KeyUserDebugs
.
decoderFlags
|=
LAST_PERIOD_VALID
;
151
}
152
// Always
153
lastPrimaryEventTimeStamp
= thisEventTimeStamp;
154
KeyUserDebugs
.
decoderFlags
|=
LAST_TIMESTAMP_VALID
;
155
156
DEBUG_TURN_PIN_OFF
(
DECODER_BENCHMARKS
,
NBIT0
,
PORTB
);
157
}
158
159
// 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
160
void
SecondaryRPMISR
(){
161
/* Clear the interrupt flag for this input compare channel */
162
TFLG
= 0x02;
163
DEBUG_TURN_PIN_ON
(
DECODER_BENCHMARKS
,
BIT0
,
PORTB
);
164
KeyUserDebugs
.
secondaryTeethSeen
++;
165
if
(
KeyUserDebugs
.
decoderFlags
&
CAM_SYNC
){
166
// check crankTeethSinceLastCamTooth to see if it's 4 or 12 and if not either of those, lose sync.
167
crankTeethSinceLastCamTooth
=
KeyUserDebugs
.
primaryTeethSeen
-
previousCrankTeethSeen
;
168
previousCrankTeethSeen
=
KeyUserDebugs
.
primaryTeethSeen
;
169
if
(
crankTeethSinceLastCamTooth
!= 4 &&
crankTeethSinceLastCamTooth
!= 12){
170
if
(
crankTeethSinceLastCamTooth
< 4){
171
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_LOW_NOISE
);
172
return
;
173
}
else
{
174
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_HIGH_NOISE
);
175
return
;
176
}
177
}
178
}
179
180
if
(!(
KeyUserDebugs
.
decoderFlags
&
OK_TO_SCHEDULE
)){
181
if
(
camTeethSeen
== 0){
182
camTeethSeen
= 1;
183
previousCrankTeethSeen
=
KeyUserDebugs
.
primaryTeethSeen
;
184
}
else
if
(
camTeethSeen
== 1){
185
camTeethSeen
= 2;
186
crankTeethSinceLastCamTooth
=
KeyUserDebugs
.
primaryTeethSeen
-
previousCrankTeethSeen
;
187
previousCrankTeethSeen
=
KeyUserDebugs
.
primaryTeethSeen
;
188
if
(
crankTeethSinceLastCamTooth
== 12){
// 12 Crank teeth in the 2 missing Cam teeth
189
SET_SYNC_LEVEL_TO
(
CAM_SYNC
);
190
KeyUserDebugs
.
currentEvent
= 0;
191
}
else
if
(
crankTeethSinceLastCamTooth
!= 4){
// 4 Crank teeth in 1 Cam tooth
192
if
(
crankTeethSinceLastCamTooth
> 4){
193
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_HIGH_NOISE
);
194
}
else
{
195
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_LOW_NOISE
);
196
}
197
}
// Else fall through and wait for a 12
198
}
else
if
(
camTeethSeen
== 2){
199
camTeethSeen
= 3;
200
crankTeethSinceLastCamTooth
=
KeyUserDebugs
.
primaryTeethSeen
-
previousCrankTeethSeen
;
201
previousCrankTeethSeen
=
KeyUserDebugs
.
primaryTeethSeen
;
202
if
(
crankTeethSinceLastCamTooth
== 12){
203
SET_SYNC_LEVEL_TO
(
CAM_SYNC
);
204
KeyUserDebugs
.
currentEvent
= 0;
205
}
else
if
(
crankTeethSinceLastCamTooth
!= 4){
206
if
(
crankTeethSinceLastCamTooth
> 4){
207
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_HIGH_NOISE
);
208
}
else
{
209
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_LOW_NOISE
);
210
}
211
}
// Else fall through and wait for a 12
212
}
else
if
(
camTeethSeen
== 3){
213
camTeethSeen
= 4;
214
crankTeethSinceLastCamTooth
=
KeyUserDebugs
.
primaryTeethSeen
-
previousCrankTeethSeen
;
215
previousCrankTeethSeen
=
KeyUserDebugs
.
primaryTeethSeen
;
216
if
(
crankTeethSinceLastCamTooth
== 12){
217
SET_SYNC_LEVEL_TO
(
CAM_SYNC
);
218
KeyUserDebugs
.
currentEvent
= 0;
219
}
else
if
(
crankTeethSinceLastCamTooth
!= 4){
220
if
(
crankTeethSinceLastCamTooth
> 4){
221
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_HIGH_NOISE
);
222
}
else
{
223
resetToNonRunningState
(
COUNT_OF_EVENTS_IMPOSSIBLY_LOW_NOISE
);
224
}
225
}
else
{
226
SET_SYNC_LEVEL_TO
(
CAM_SYNC
);
// Set the sync on the eventAngle[12] 360 degrees
227
KeyUserDebugs
.
currentEvent
= 12;
228
}
229
}
else
if
(
camTeethSeen
== 4){
// Guaranteed to have already synced
230
// If this crank teeth seen wasn't a valid number, it would have never made it here, having returned in the block near the top of the ISR
231
SET_SYNC_LEVEL_TO
(
CAM_SYNC
);
// Add sync confirmation point
232
}
else
{
233
resetToNonRunningState
(
BUG_REACHED_UNREACHABLE_CODE
);
234
}
235
}
236
DEBUG_TURN_PIN_OFF
(
DECODER_BENCHMARKS
,
NBIT0
,
PORTB
);
237
}
Generated on Sat Jun 6 2015 07:41:33 for FreeEMS by
1.8.1.2