2015-05-28 16:49:44 -07:00
/*
Speeduino - Simple engine management for the Arduino Mega 2560 platform
Copyright ( C ) Josh Stewart
A full copy of the license may be found in the projects root directory
*/
2014-05-06 04:07:49 -07:00
/*
Timers are used for having actions performed repeatedly at a fixed interval ( Eg every 100 ms )
They should not be confused with Schedulers , which are for performing an action once at a given point of time in the future
2014-01-30 20:02:32 -08:00
2014-05-06 04:07:49 -07:00
Timers are typically low resolution ( Compared to Schedulers ) , with maximum frequency currently being approximately every 10 ms
*/
2015-02-14 09:04:00 -08:00
# include "timers.h"
# include "globals.h"
2016-06-24 01:02:53 -07:00
# include "sensors.h"
2014-01-30 20:02:32 -08:00
2014-02-06 01:48:19 -08:00
void initialiseTimers ( )
{
2016-06-24 01:02:53 -07:00
# if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //AVR chips use the ISR for this
2015-04-13 21:41:44 -07:00
//Configure Timer2 for our low-freq interrupt code.
2014-02-06 01:48:19 -08:00
TCCR2B = 0x00 ; //Disbale Timer2 while we set it up
2015-04-13 21:41:44 -07:00
TCNT2 = 131 ; //Preload timer2 with 131 cycles, leaving 125 till overflow. As the timer runs at 125Khz, this causes overflow to occur at 1Khz = 1ms
2014-02-06 01:48:19 -08:00
TIFR2 = 0x00 ; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
TIMSK2 = 0x01 ; //Timer2 Set Overflow Interrupt enabled.
TCCR2A = 0x00 ; //Timer2 Control Reg A: Wave Gen Mode normal
2015-04-13 21:41:44 -07:00
/* Now configure the prescaler to CPU clock divided by 128 = 125Khz */
2015-02-09 05:00:16 -08:00
TCCR2B | = ( 1 < < CS22 ) | ( 1 < < CS20 ) ; // Set bits
TCCR2B & = ~ ( 1 < < CS21 ) ; // Clear bit
2016-06-24 01:02:53 -07:00
# endif
2014-01-30 20:02:32 -08:00
}
//Timer2 Overflow Interrupt Vector, called when the timer overflows.
2015-04-13 21:41:44 -07:00
//Executes every ~1ms.
2016-06-24 01:02:53 -07:00
# if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //AVR chips use the ISR for this
2015-06-05 06:30:37 -07:00
ISR ( TIMER2_OVF_vect , ISR_NOBLOCK )
2016-06-24 01:02:53 -07:00
# elif defined (CORE_TEENSY) && defined (__MK20DX256__)
void timer2Overflowinterrupt ( ) //Most ARM chips can simply call a function
# endif
2014-01-30 20:02:32 -08:00
{
//Increment Loop Counters
2014-05-06 04:07:49 -07:00
loop250ms + + ;
2014-01-30 20:02:32 -08:00
loopSec + + ;
2015-02-09 05:19:58 -08:00
//Overdwell check
2016-07-19 21:56:11 -07:00
targetOverdwellTime = micros ( ) - ( 1000 * configPage2 . dwellLimit ) ; //Set a target time in the past that all coil charging must have begun after. If the coil charge began before this time, it's been running too long
targetTachoPulseTime = micros ( ) - ( 1500 ) ;
2015-02-09 05:19:58 -08:00
//Check first whether each spark output is currently on. Only check it's dwell time if it is
2015-09-07 18:17:47 -07:00
if ( ignitionSchedule1 . Status = = RUNNING ) { if ( ignitionSchedule1 . startTime < targetOverdwellTime & & configPage2 . useDwellLim ) { endCoil1Charge ( ) ; } if ( ignitionSchedule1 . startTime < targetTachoPulseTime ) { digitalWrite ( pinTachOut , HIGH ) ; } }
if ( ignitionSchedule2 . Status = = RUNNING ) { if ( ignitionSchedule2 . startTime < targetOverdwellTime & & configPage2 . useDwellLim ) { endCoil2Charge ( ) ; } if ( ignitionSchedule2 . startTime < targetTachoPulseTime ) { digitalWrite ( pinTachOut , HIGH ) ; } }
if ( ignitionSchedule3 . Status = = RUNNING ) { if ( ignitionSchedule3 . startTime < targetOverdwellTime & & configPage2 . useDwellLim ) { endCoil3Charge ( ) ; } if ( ignitionSchedule3 . startTime < targetTachoPulseTime ) { digitalWrite ( pinTachOut , HIGH ) ; } }
2016-05-28 05:06:48 -07:00
if ( ignitionSchedule4 . Status = = RUNNING ) { if ( ignitionSchedule4 . startTime < targetOverdwellTime & & configPage2 . useDwellLim ) { endCoil4Charge ( ) ; } if ( ignitionSchedule4 . startTime < targetTachoPulseTime ) { digitalWrite ( pinTachOut , HIGH ) ; } }
2015-02-09 05:00:16 -08:00
2015-04-13 21:41:44 -07:00
//Loop executed every 250ms loop (1ms x 250 = 250ms)
2014-05-06 04:07:49 -07:00
//Anything inside this if statement will run every 250ms.
2015-02-09 05:00:16 -08:00
if ( loop250ms = = 250 )
2014-01-30 20:02:32 -08:00
{
2014-05-06 04:07:49 -07:00
loop250ms = 0 ; //Reset Counter.
2014-01-30 20:02:32 -08:00
}
2015-04-13 21:41:44 -07:00
//Loop executed every 1 second (1ms x 1000 = 1000ms)
2015-02-09 05:00:16 -08:00
if ( loopSec = = 1000 )
2014-01-30 20:02:32 -08:00
{
loopSec = 0 ; //Reset counter.
2014-02-06 01:48:19 -08:00
2014-02-17 22:08:55 -08:00
//**************************************************************************************************************************************************
//This updates the runSecs variable
2014-02-06 01:48:19 -08:00
//If the engine is running or cranking, we need ot update the run time counter.
2014-12-23 15:25:51 -08:00
if ( BIT_CHECK ( currentStatus . engine , BIT_ENGINE_RUN ) )
2014-02-06 01:48:19 -08:00
{ //NOTE - There is a potential for a ~1sec gap between engine crank starting and ths runSec number being incremented. This may delay ASE!
if ( currentStatus . runSecs < = 254 ) //Ensure we cap out at 255 and don't overflow. (which would reset ASE)
{ currentStatus . runSecs + + ; } //Increment our run counter by 1 second.
}
2014-02-17 22:08:55 -08:00
//**************************************************************************************************************************************************
//This records the number of main loops the system has completed in the last second
currentStatus . loopsPerSecond = mainLoopCount ;
mainLoopCount = 0 ;
//**************************************************************************************************************************************************
2014-05-08 03:46:38 -07:00
//increament secl (secl is simply a counter that increments every second and is used to track whether the system has unexpectedly reset
currentStatus . secl + + ;
2016-06-24 01:02:53 -07:00
//**************************************************************************************************************************************************
2015-06-02 05:56:18 -07:00
//Check the fan output status
if ( configPage4 . fanEnable = = 1 )
{
fanControl ( ) ; // Fucntion to turn the cooling fan on/off
}
2015-12-20 20:45:52 -08:00
//Check whether fuel pump priming is complete
if ( ! fpPrimed )
{
if ( currentStatus . secl > = configPage1 . fpPrime )
{
fpPrimed = true ; //Mark the priming as being completed
if ( currentStatus . RPM = = 0 ) { digitalWrite ( pinFuelPump , LOW ) ; fuelPumpOn = false ; } //If we reach here then the priming is complete, however only turn off the fuel pump if the engine isn't running
}
}
2016-06-24 01:02:53 -07:00
//**************************************************************************************************************************************************
//Set the flex reading (if enabled). The flexCounter is updated with every pulse from the sensor. If cleared once per second, we get a frequency reading
if ( configPage1 . flexEnabled )
{
2016-06-26 17:31:52 -07:00
if ( flexCounter < 50 )
2016-06-24 01:02:53 -07:00
{
2016-06-26 17:31:52 -07:00
currentStatus . flex = 0 ; //Standard GM Continental sensor reads from 50Hz (0 ethanol) to 150Hz (Pure ethanol). Subtracting 50 from the frequency therefore gives the ethanol percentage.
flexCounter = 0 ;
}
else if ( flexCounter > 151 ) //1 pulse buffer
{
if ( flexCounter < 169 )
{
currentStatus . flex = 100 ; //Standard GM Continental sensor reads from 50Hz (0 ethanol) to 150Hz (Pure ethanol). Subtracting 50 from the frequency therefore gives the ethanol percentage.
flexCounter = 0 ;
}
else
{
//This indicates an error condition. Spec of the sensor is that errors are above 170Hz)
currentStatus . flex = 0 ;
flexCounter = 0 ;
}
2016-06-24 01:02:53 -07:00
}
else
{
currentStatus . flex = flexCounter - 50 ; //Standard GM Continental sensor reads from 50Hz (0 ethanol) to 150Hz (Pure ethanol). Subtracting 50 from the frequency therefore gives the ethanol percentage.
flexCounter = 0 ;
}
}
2014-02-18 02:05:13 -08:00
}
2016-06-24 01:02:53 -07:00
# if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //AVR chips use the ISR for this
//Reset Timer2 to trigger in another ~1ms
2015-04-13 21:41:44 -07:00
TCNT2 = 131 ; //Preload timer2 with 100 cycles, leaving 156 till overflow.
2014-01-30 20:02:32 -08:00
TIFR2 = 0x00 ; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
2016-06-24 01:02:53 -07:00
# endif
2014-01-30 20:02:32 -08:00
}