1 /* FreeEMS - the open source engine management system
3 * Copyright 2008 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!
27 /** @file realtimeISRs.c
28 * @ingroup interruptHandlers
30 * @brief Real time interrupts
32 * This file contains real time interrupt handlers. Mainly it holds the RTI
33 * handler itself, however the modulus down counter and ETC timer overflow
34 * functions are here too.
40 #define REALTIMEISRS_C
41 #include "inc/freeEMS.h"
42 #include "inc/interrupts.h"
43 #include "inc/commsISRs.h"
46 /** @brief Real Time Interrupt Handler
48 * Handles time keeping, including all internal clocks, and generic periodic
49 * tasks that run quickly and must be done on time.
54 /* Clear the RTI flag */
57 /* Record time stamp for code run time reporting */
58 unsigned short startTimeRTI
= TCNT
;
60 /* Increment the counter */
61 Clocks
.realTimeClockMain
++;
63 /* This function could be performed without the extra variables by rolling over the main ones at the largest multiples of the next ones, but I'm not sure thats better */
65 // TODO add content to eighths of a milli RTC ?
67 /* Every 8th RTI execution is one milli */
68 if(Clocks
.realTimeClockMain
% 8 == 0){
69 /* Increment the milli counter */
70 Clocks
.realTimeClockMillis
++;
72 /* Increment the milli roll over variable */
73 Clocks
.millisToTenths
++;
75 /* Perform all tasks that are once per millisecond here or preferably main */
76 Clocks
.timeoutADCreadingClock
++;
77 if(Clocks
.timeoutADCreadingClock
> fixedConfigs2
.sensorSettings
.readingTimeout
){
78 /* Set force read adc flag */
79 coreStatusA
|= FORCE_READING
;
80 Clocks
.timeoutADCreadingClock
= 0;
83 /* Every 100 millis is one tenth */
84 if(Clocks
.millisToTenths
% 100 == 0){
85 /* Increment the tenths counter */
86 Clocks
.realTimeClockTenths
++;
88 /* Increment the tenths roll over variable */
89 Clocks
.tenthsToSeconds
++;
91 /* Reset the millis roll over variable */
92 Clocks
.millisToTenths
= 0;
94 /* Perform all tasks that are once per tenth of a second here or preferably main */
95 // decrement port H debounce variable till it's zero again.
96 if(portHDebounce
!= 0){
100 /* Every 10 tenths is one second */
101 if(Clocks
.tenthsToSeconds
% 10 == 0){
102 /* Increment the seconds counter */
103 Clocks
.realTimeClockSeconds
++;
105 /* Increment the seconds roll over variable */
106 Clocks
.secondsToMinutes
++;
108 /* Reset the tenths roll over variable */
109 Clocks
.tenthsToSeconds
= 0;
110 /* Perform all tasks that are once per second here or preferably main */
112 // temp throttling for log due to tuner performance issues (in the bedroom)
113 ShouldSendLog
= TRUE
;
114 /* Flash the user LED as a "heartbeat" to let new users know it's alive */
117 /* Every 60 seconds is one minute, 65535 minutes is enough for us :-) */
118 if(Clocks
.secondsToMinutes
% 60 == 0){
119 /* Increment the minutes counter */
120 Clocks
.realTimeClockMinutes
++;
122 /* Potentially put an hours field in here and below, but that would be excessive */
123 // TODO add hours RTC ?
125 /* Reset the seconds roll over variable */
126 Clocks
.secondsToMinutes
= 0;
128 /* Perform all tasks that are once per minute here or preferably main */
129 // TODO add content in minutes RTC ?
131 /* Hours if statement here if we do hours which we probably won't */
136 RuntimeVars
.RTCRuntime
= TCNT
- startTimeRTI
;
140 /** @brief Tacho pulse generator
142 * Currently this is being used to generate a variable frequency tachometer
143 * output. Although this is a bit of a waste of a timer resource it does allow
144 * tachometers that were intended for engines with a different cylinder count
145 * to be used where it would otherwise not be possible.
149 void ModDownCtrISR(){
150 /* Clear the modulus down counter interrupt flag */
153 /* If the rpm isn't genuine go ultra slow */
154 if(engineCyclePeriod
== ticksPerCycleAtOneRPM
){
157 /* Use engine cycle period to setup the frequency of this counter and thereby act as a tacho out */
158 tachoPeriod
= (unsigned long)engineCyclePeriod
/ fixedConfigs1
.tachoSettings
.tachoTotalFactor
;
160 /* Set the count down value */
163 /* Bit bang the output port */
164 PORTA
^= 0x40; // SM pin (A6)
168 /** @brief ECT overflow handler
170 * When the ECT free running timer hits 65535 and rolls over, this is run. Its
171 * job is to extend the timer to an effective 32 bits for longer measuring much
172 * longer periods with the same resolution.
176 void TimerOverflow(){
177 /* Increment the timer extension variable */
178 timerExtensionClock
++;
180 /* Clear the timer overflow interrupt flag */
185 /** @todo TODO This could be useful in future once sleeping is implemented.
186 // Generic periodic interrupt (This only works from wait mode...)
188 // Clear the flag needs check because writing a 1 can set this one
189 //if(VREGAPICL & 0x01){ // if the flag is set...
190 VREGAPICL |= 0x01; // clear it...
191 //} // and not otherwise!