1 /* FreeEMS - the open source engine management system
3 * Copyright 2009 Sean Keys
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!
28 * @ingroup interruptHandlers
29 * @ingroup enginePositionRPMDecoders
31 * @brief LT1 Optispark
33 * Uses PT1 to interrupt on rising and falling events of the 8x cam sensor track.
34 * A certain number of 360x teeth will pass while PT1 is in a high or low state.
35 * Using that uniquek count we can set the positing of your Virtual CAS clock.
36 * After VCAS's position is set set PT7 to only interrupt on every 5th tooth, lowering
37 * the amount of interrupts generated, to a reasonable level.
39 * @note Pseudo code that does not compile with zero warnings and errors MUST be commented out.
41 * @todo TODO This file contains SFA but Sean Keys is going to fill it up with
42 * @todo TODO wonderful goodness very soon ;-)
49 #include "inc/freeEMS.h"
50 #include "inc/interrupts.h"
51 #include "inc/LT1-360-8.h"
54 unsigned short VCAS
= 0; /* create our virtual Cam Angle Sensor */
56 /** Setup PT Capturing so that we can decode the LT1 pattern
57 * @todo TODO Put this in the correct place
61 /* set pt1 to capture on rising and falling */
66 /* set overflow to 8 so that it will fire an interrupt on every 8th tooth, basically making it a 45tooth CAS */
69 * @todo TODO Docs here!
71 void PrimaryRPMISR(void){
72 /* Clear the interrupt flag for this input compare channel */
75 /* Save all relevant available data here */
76 // unsigned short codeStartTimeStamp = TCNT; /* Save the current timer count */
77 // unsigned short edgeTimeStamp = TC0; /* Save the edge time stamp */
78 unsigned char PTITCurrentState
= PTIT
; /* Save the values on port T regardless of the state of DDRT */
79 // unsigned short PORTS_BACurrentState = PORTS_BA; /* Save ignition output state */
81 // unsigned char risingEdge; /* in LT1s case risingEdge means signal is high */
82 // if(fixedConfigs1.coreSettingsA & PRIMARY_POLARITY){
83 // risingEdge = PTITCurrentState & 0x01;
85 // risingEdge = !(PTITCurrentState & 0x01);
88 PORTJ
|= 0x80; /* Echo input condition on J7 */
89 if(!isSynced
){ /* If the CAS is not in sync get window counts so SecondaryRPMISR can set position */
90 if (PTITCurrentState
& 0x02){
91 PrimaryTeethDuringHigh
++; /* if low resolution signal is high count number of pulses */
93 PrimaryTeethDuringLow
++; /* if low resolution signal is low count number of pulses */
95 }else{ /* The CAS is synced and we need to update our 360/5=72 tooth wheel */
96 /// @todo TODO possibly add code to make sure we are in divide mode, if not error out
97 VCAS
= VCAS
+ 10; /* Check/correct for 10deg of CAM movement */
98 /// @todo TODO fill in or remove the else
103 /** Secondary RPM ISR
104 * @brief Use the rising and falling edges...................
105 * @todo TODO Docs here!
106 * @todo TODO Add a check for 1 skip pulse of the 8x track, to prevent possible incorrect sync.
107 * @todo TODO Possibly make virtual CAS 16-bit so was can get rid of floating points and use for syncing
109 void SecondaryRPMISR(void){
110 /* Clear the interrupt flag for this input compare channel */
113 /* Save all relevant available data here */
114 // unsigned short codeStartTimeStamp = TCNT; /* Save the current timer count */
115 // unsigned short edgeTimeStamp = TC1; /* Save the timestamp */
116 unsigned char PTITCurrentState
= PTIT
; /* Save the values on port T regardless of the state of DDRT */
117 // unsigned short PORTS_BACurrentState = PORTS_BA; /* Save ignition output state */
118 unsigned char risingEdge
;
119 if(fixedConfigs1
.coreSettingsA
& PRIMARY_POLARITY
){
120 risingEdge
= PTITCurrentState
& 0x01;
122 risingEdge
= !(PTITCurrentState
& 0x01);
124 PORTJ
|= 0x40; /* echo input condition */
126 if (!isSynced
& risingEdge
){ /* If the CAS is not in sync get window counts and set virtual CAS position */
127 /* if signal is high that means we can count the lows */
128 switch (PrimaryTeethDuringLow
){
129 case 23: /* wheel is at 0 deg TDC #1, set our virtual CAS to tooth 0 of 720 */
132 changeSyncStatus((unsigned char) 1);
135 case 38: /* wheel is at 90 deg TDC #4, set our virtual CAS to tooth 180 of 720 */
138 changeSyncStatus((unsigned char) 1);
141 case 33: /* wheel is at 180 deg TDC #6 set our virtual CAS to tooth 360 of 720 */
144 changeSyncStatus((unsigned char) 1);
147 case 28: /* wheel is at 270 deg TDC #7 set our virtual CAS to tooth 540 of 720 */
150 changeSyncStatus((unsigned char) 1);
155 Counters
.crankSyncLosses
++; /* use crankSyncLosses variable to store number of invalid count cases while attempting to sync*/
158 PrimaryTeethDuringLow
= 0; /* In any case reset counter */
161 if(!isSynced
& !risingEdge
){/* if the signal is low that means we can count the highs */
162 switch (PrimaryTeethDuringHigh
){ /* will need to additional code to off-set the initialization of PACNT since they are not
163 evenly divisible by 5 */
164 case 7: /* wheel is at 52 deg, 7 deg ATDC #8 set our virtual CAS to tooth 104 of 720 */
169 case 12: /* wheel is at 147 deg, 12 deg ATDC #3 set our virtual CAS to tooth 294 of 720 */
174 case 17: /* wheel is at 242 deg, 17 deg ATDC #5 set our virtual CAS to tooth 484 of 720 */
179 case 22: /* wheel is at 337 deg, 22 deg ATDC #2 set our virtual CAS to tooth 674 of 720 */
186 Counters
.crankSyncLosses
++; /* use crankSyncLosses variable to store number of invalid/default count cases while attempting to sync*/
191 PrimaryTeethDuringHigh
= 0; /* In any case reset counter */
193 if(isSynced
& risingEdge
){ /* We are in sync and need to make sure our counts are good */
195 /* System is synced so use adjusted count numbers to check sync */
196 /// @todo TODO fill in or remove the else
199 // Counter.primaryTeethAfterSecondaryRise = 0;
200 // Counter.primaryTeethAfterSecondaryFall = 0;
202 // unsigned char risingEdge;
203 // if(fixedConfigs1.coreSettingsA & SECONDARY_POLARITY){
204 // risingEdge = PTITCurrentState & 0x02;
206 // risingEdge = !(PTITCurrentState & 0x02);
209 /** PT0 Accumulator Mode
210 * @brief Change the accumulator mode to overflow every 5 inputs on PT0 making our 360
211 * tooth wheel interrupt like a 72 tooth wheel
213 @todo TODO Decide if an explicit parameter is necessary if not use a existing status var instead for now it's explicit.
215 void changeSyncStatus(unsigned char synced
){
216 if (synced
!= 1) { /* disable accumulator counter, so an ISR is fired on all 360 teeth */
217 PACTL
= 0x00; /* disable PAEN and PBOIV */
218 /* (PACTL) 7 6 5 4 3 2 1 0
219 PAEN PAMOD PEDGE CLK1 CLK0 PAOVI PAI */
220 }else{ /* enable accumulator so an ISR is only fired on every "5th tooth of the 360x track" */
221 // TIOS = TIOS & "0xCC0x83" WTF!?LOL!! 0x80; /* PT7 input */
222 // TCTL1 = TCTL1 & "0xCC0x83" WTF!?LOL!! 0xC0; /* Disconnect IC/OC logic from PT7 */
223 TIOS
= TIOS
& 0x80; /* PT7 input */
224 TCTL1
= TCTL1
& 0xC0; /* Disconnect IC/OC logic from PT7 */
225 /// @todo TODO the register below does not exist and I couldn't figure out what you meant to do...
226 PACN0
= 0xFB ; /* Calculation, $00 – $05 = $FB. This will overflow in 5 more edges. */
227 PACTL
= 0x52; /* Enable PA in count mode, rising edge and interrupt on overflow 01010010 */