1 /* FreeEMS - the open source engine management system
3 * Copyright 2008-2013 Fred Cooke
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!
29 * @ingroup interruptHandlers
31 * @brief Miscellaneous Interrupt Handlers
33 * Various non-descript interrupt handlers that don't really fit anywhere else
34 * and aren't big enough to live on their own just yet.
38 #include "inc/freeEMS.h"
39 #include "inc/interrupts.h"
40 #include "inc/decoderInterface.h"
44 /** @brief Unimplemented Interrupt Handler
46 * Unimplemented interrupt service routine for calls we weren't expecting.
47 * Currently this simply counts bad calls like any other event type.
49 * @todo TODO Split this into its own file, create one for each, and clear flags for all, and increment shared counter as is.
50 * @todo TODO Currently not a problem, but as indirectly pointed out by johntramp, if no flag clearing is being done, then this code will run continuously, which is not a good idea...
53 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
54 FLAG_AND_INC_FLAGGABLE(FLAG_CALLS_TO_UISRS_OFFSET
);
55 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
58 /** @brief Spurious Interrupt Handler
60 * This is fired when the correct vector for an interrupt can not be determined.
62 * Theoretically this should not happen, and probably indicates a code fault.
64 void SpuriousISR(void){
66 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
67 FLAG_AND_INC_FLAGGABLE2(FLAG_SPURIOUS_INTERRUPTS_OFFSET
);
68 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
71 /** @brief Unimplemented Opcode Handler
73 * Unimplemented opcode trap. This should never run and probably indicates an
74 * attempt to execute data instead of code, but could be an assembler issue.
76 void UnimplOpcodeISR(void){
78 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
79 FLAG_AND_INC_FLAGGABLE2(FLAG_UNIMPLEMENTED_OPCODES_OFFSET
);
80 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
83 /** @brief CPU RAM Access Violation Handler
85 * If the CPU tries to access protected XGATE RAM, this is fired.
87 void RAMViolationISR(void){
90 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
91 FLAG_AND_INC_FLAGGABLE2(FLAG_RAM_ACCESS_VIOLATIONS_OFFSET
);
92 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
95 /** @brief XGATE Software Error Handler
97 * If buggy code is being executed on the XGATE, this may fire alerting us to it.
99 void XGATEErrorISR(void){
101 XGMCTL
= (XGSWEIFM
| XGSWEIF
);
102 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
103 FLAG_AND_INC_FLAGGABLE2(FLAG_XGATE_SOFTWARE_ERRORS_OFFSET
);
104 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
107 /** @brief PLL Lock Lost/Gained
109 * When the Phase Locked Loop is lost or gained, this is called.
111 void PLLLockISR(void){
114 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
115 // Check the state of PLL lock
116 if(CRGFLG
& PLLLOCK
){ // Recovered
117 // Re-enable outputs with return of accurate clock
118 ((ignitionCutFlags
*)&KeyUserDebugs
.ignitionCuts
)->IgnLostPLL
= 0;
119 ((injectionCutFlags
*)&KeyUserDebugs
.injectionCuts
)->InjLostPLL
= 0;
121 // Record the loss of PLL lock
122 FLAG_AND_INC_FLAGGABLE(FLAG_PHASE_LOCKED_LOOP_LOCK_LOST_OFFSET
);
123 // Force sync loss with special code to prevent engine damage from incorrect timings
124 // This is required otherwise we never see the self clock code, as it's immediately over-written by our code
125 if(KeyUserDebugs
.syncLostWithThisID
== SELF_CLOCK_MODE_PRECAUTIONARY
){
126 // Don't over-write the self clock sync loss ID
127 resetToNonRunningState(SELF_CLOCK_MODE_PRECAUTIONARY
);
129 // This means ONLY the PLL lock was lost (at this time)
130 resetToNonRunningState(PLL_LOCK_LOST_PRECAUTIONARY
);
132 // Disable outputs as a precaution with dodgy clock
133 ((ignitionCutFlags
*)&KeyUserDebugs
.ignitionCuts
)->IgnLostPLL
= 1;
134 ((injectionCutFlags
*)&KeyUserDebugs
.injectionCuts
)->InjLostPLL
= 1;
136 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
139 /** @brief Self Clock Mode Entered/Exited
141 * When the main clock quality drops too low to be used, self clock is entered.
143 * See section 2.6.3 of the device manual for more information.
145 void SelfClockISR(void){
148 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
149 // Check the state of self clock mode flag
150 if(CRGFLG
& SCM
){ // Self Clock Mode
151 // Record the loss of main clock
152 FLAG_AND_INC_FLAGGABLE(FLAG_SELF_CLOCK_MODE_ENTERED_OFFSET
);
153 // Force sync loss with special code to prevent engine damage from incorrect timings
154 resetToNonRunningState(SELF_CLOCK_MODE_PRECAUTIONARY
);
155 // Disable outputs as a precaution with dodgy clock
156 ((ignitionCutFlags
*)&KeyUserDebugs
.ignitionCuts
)->IgnSelfClock
= 1;
157 ((injectionCutFlags
*)&KeyUserDebugs
.injectionCuts
)->InjSelfClock
= 1;
159 // Disabled when falling back to Self Clock Mode, re-enable here
160 enablePLL(); // Note, busy wait with no limit, danger to the manifold!
162 // Re-enable outputs with return of accurate clock
163 ((ignitionCutFlags
*)&KeyUserDebugs
.ignitionCuts
)->IgnSelfClock
= 0;
164 ((injectionCutFlags
*)&KeyUserDebugs
.injectionCuts
)->InjSelfClock
= 0;
166 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
169 /** @brief Port P pins ISR
171 * Interrupt handler for edge events on port P pins. Not currently used.
174 /* Clear all port P flags (we only want one at a time) */
176 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
177 FLAG_AND_INC_FLAGGABLE(FLAG_CALLS_TO_UISRS_OFFSET
);
178 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
182 /** @brief Port J pins ISR
184 * Interrupt handler for edge events on port J pins. Not currently used.
187 /* Clear all port H flags (we only want one at a time) */
189 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
190 FLAG_AND_INC_FLAGGABLE(FLAG_CALLS_TO_UISRS_OFFSET
);
191 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
195 /** @brief Port H pins ISR
197 * Interrupt handler for edge events on port H pins. Not currently used.
201 // // read the interrupt flags to a variable
202 // unsigned char portHFlags = PIFH;
203 // portHFlags &= 0xF8; // mask out the other bits
205 // /* Clear all port H flags (we only want one at a time) */
207 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
209 // Bump this for the time being as this should not be occurring.
210 FLAG_AND_INC_FLAGGABLE(FLAG_CALLS_TO_UISRS_OFFSET
);
212 // // Toggle a LED so we can see if the code ran
213 // PO-don't use this-RTA ^= 0x80; // Fuel pump pin (A7)
216 if(portHDebounce
== 0){
222 // // find out which pin triggered it, clear the flag, perform the action.
223 // switch(portHFlags)
225 // case 0x80 : // Increment cylinder count and set port count appropriately.
226 // switch (configs.combustionEventsPerEngineCycle) {
228 // configs.combustionEventsPerEngineCycle = 2;
229 // configs.ports = 2;
232 // configs.combustionEventsPerEngineCycle = 3;
233 // configs.ports = 3;
236 // configs.combustionEventsPerEngineCycle = 4;
237 // configs.ports = 4;
240 // configs.combustionEventsPerEngineCycle = 5;
241 // configs.ports = 5;
244 // configs.combustionEventsPerEngineCycle = 6;
245 // configs.ports = 6;
248 // configs.combustionEventsPerEngineCycle = 8;
249 // configs.ports = 4;
252 // configs.combustionEventsPerEngineCycle = 10;
253 // configs.ports = 5;
256 // configs.combustionEventsPerEngineCycle = 12;
257 // configs.ports = 6;
260 // configs.combustionEventsPerEngineCycle = 1;
261 // configs.ports = 1;
265 // case 0x40 : // Injection output enable/disable
267 // case 0x20 : // Ignition output enable/disable
269 // case 0x10 : // Staged injection enable/disable
271 // case 0x08 : // Staged injection start sched/fixed
273 // case 0x04 : // Staged injection end sched/fixed
275 // case 0x02 : // free input
277 // case 0x01 : // free input
279 // default : // Two or more pressed, nothing to do except wait for another button press
282 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
286 /** @brief IRQ/PE1 pin ISR
288 * Interrupt handler for edge events on the IRQ/PE1 pin. Not currently used.
293 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
294 FLAG_AND_INC_FLAGGABLE(FLAG_CALLS_TO_UISRS_OFFSET
);
295 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
299 /** @brief XIRQ/PE0 pin ISR
301 * Interrupt handler for edge events on the XIRQ/PE0 pin. Not currently used.
306 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT7
, PORTB
);
307 FLAG_AND_INC_FLAGGABLE(FLAG_CALLS_TO_UISRS_OFFSET
);
308 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT7
, PORTB
);
312 /** @brief Low Voltage Counter
314 * Count how often our voltage drops lower than it should without resetting.
316 void LowVoltageISR(void){
319 DEBUG_TURN_PIN_ON(DECODER_BENCHMARKS
, BIT6
, PORTB
);
320 FLAG_AND_INC_FLAGGABLE(FLAG_LOW_VOLTAGE_CONDITION_OFFSET
);
321 DEBUG_TURN_PIN_OFF(DECODER_BENCHMARKS
, NBIT6
, PORTB
);