2013-02-13 03:49:36 -08:00
/*
This scheduler is designed to maintain 2 schedules for use by the fuel and ignition systems .
It functions by waiting for the overflow vectors from each of the timers in use to overflow , which triggers an interrupt
//Technical
2013-02-13 22:34:29 -08:00
Currently I am prescaling the 16 - bit timers to 256. This means that the counter increments every 16u s and will overflow every 1048576u S
2013-02-13 03:49:36 -08:00
Max Period = ( Prescale ) * ( 1 / Frequency ) * ( 2 ^ 17 )
( See http : //playground.arduino.cc/code/timer1)
2013-02-13 22:34:29 -08:00
This means that the precision of the scheduler is 16u S ( + / - 8u S of target )
2013-02-13 03:49:36 -08:00
/ Features
This differs from most other schedulers in that its calls are non - recurring ( IE You schedule an event at a certain time and once it has occurred , it will not reoccur unless you explicitely ask for it )
Each timer can have only 1 callback associated with it at any given time . If you call the setCallback function a 2 nd time , the original schedule will be overwritten and not occur
Timer identification
2013-02-13 13:51:29 -08:00
The Arduino timer3 is used for schedule 1
The Arduino timer4 is used for schedule 2
Both of these are 16 - bit timers ( ie count to 65536 )
See page 136 of the processors datasheet : http : //www.atmel.com/Images/doc2549.pdf
256 prescale gives tick every 16u S
256 prescale gives overflow every 1048576u S ( This means maximum wait time is 1.0485 seconds )
2013-02-13 03:49:36 -08:00
*/
# include <avr/interrupt.h>
# include <avr/io.h>
2013-02-13 22:34:29 -08:00
//#define clockspeed 16000000
2013-02-13 03:49:36 -08:00
2013-02-14 04:19:34 -08:00
int schedule1Active ; //Value=0 means do nothing, value=1 means call the startCallback, value=2 means call the endCallback
2013-02-13 03:49:36 -08:00
int schedule2Active ;
2013-02-14 04:19:34 -08:00
unsigned long schedule1Duration ; //How long (uS) after calling the start callback to we call the end callback
unsigned long schedule2Duration ;
void ( * schedule1StartCallback ) ( ) ; //Start Callback function for schedule1
void ( * schedule2StartCallback ) ( ) ;
void ( * schedule1EndCallback ) ( ) ; //End Callback function for schedule1
void ( * schedule2EndCallback ) ( ) ;
2013-02-13 03:49:36 -08:00
void initialiseScheduler ( )
{
// Much help in this from http://arduinomega.blogspot.com.au/2011/05/timer2-and-overflow-interrupt-lets-get.html
2013-02-13 22:34:29 -08:00
//Schedule 1, which is uses timer 3
2013-02-13 03:49:36 -08:00
TCCR3B = 0x00 ; //Disbale Timer2 while we set it up
2013-02-13 22:34:29 -08:00
TCNT3 = 0 ; //Reset Timer Count
2013-02-13 03:49:36 -08:00
TIFR3 = 0x00 ; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
TIMSK3 = 0x01 ; //Timer2 INT Reg: Timer2 Overflow Interrupt Enable
TCCR3A = 0x00 ; //Timer2 Control Reg A: Wave Gen Mode normal
TCCR3B = ( 1 < < CS12 ) ; //Timer2 Control Reg B: Timer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
2013-02-13 22:34:29 -08:00
//Schedule 2, which is uses timer 4
TCCR4B = 0x00 ; //Disbale Timer2 while we set it up
TCNT4 = 0 ; //Reset Timer Count
TIFR4 = 0x00 ; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
TIMSK4 = 0x01 ; //Timer2 INT Reg: Timer2 Overflow Interrupt Enable
TCCR4A = 0x00 ; //Timer2 Control Reg A: Wave Gen Mode normal
TCCR4B = ( 1 < < CS12 ) ; //Timer2 Control Reg B: Timer Prescaler set to 256. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
2013-02-13 03:49:36 -08:00
2013-02-13 22:47:49 -08:00
schedule1Active = 0 ;
schedule2Active = 0 ;
2013-02-13 03:49:36 -08:00
}
/*
2013-02-14 04:19:34 -08:00
This turns schedule 1 on , gives it callback functions and resets the relevant timer based on the time in the future that this should be triggered
2013-02-13 03:49:36 -08:00
Args :
2013-02-14 04:19:34 -08:00
startCallback : The function to be called once the timeout1 is reached
timeout1 : The number of uS in the future that the callback should be triggered
duration : The number of uS before endCallback is called
endCallback
2013-02-13 03:49:36 -08:00
*/
2013-02-14 04:19:34 -08:00
void setSchedule1 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) )
2013-02-13 03:49:36 -08:00
{
//We need to calculate the value to reset the timer to (preload) in order to achieve the desired overflow time
//As the timer is ticking every 16uS (Time per Tick = (Prescale)*(1/Frequency))
2013-02-13 13:51:29 -08:00
//TODO: Need to add check for timeout > 1048576 ????
TCNT3 = 65536 - ( timeout / 16 ) ; //Each tick occurs every 16uS with a 256 prescaler so divide the timeout by 16 to get ther required number of ticks. Subtract this from the total number of tick (65536 for 16-bit timer)
2013-02-14 04:19:34 -08:00
schedule1Duration = duration ;
schedule1StartCallback = startCallback ; //Name the start callback function
schedule1EndCallback = endCallback ; //Name the start callback function
schedule1Active = 1 ; //Turn this schedule on and set it
2013-02-13 03:49:36 -08:00
}
2013-02-13 22:34:29 -08:00
//As above, but for schedule2
2013-02-14 04:19:34 -08:00
void setSchedule2 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) )
2013-02-13 22:34:29 -08:00
{
//TODO: Need to add check for timeout > 1048576 ????
TCNT4 = 65536 - ( timeout / 16 ) ; //Each tick occurs every 16uS with a 256 prescaler so divide the timeout by 16 to get ther required number of ticks. Subtract this from the total number of tick (65536 for 16-bit timer)
2013-02-14 04:43:18 -08:00
schedule2Duration = duration ;
2013-02-14 04:19:34 -08:00
schedule2StartCallback = startCallback ; //Name the callback function
schedule2EndCallback = endCallback ; //Name the callback function
2013-02-13 22:34:29 -08:00
schedule2Active = 1 ; //Turn this schedule on
}
//Timer3 (schedule 1) Overflow Interrupt Vector
2013-02-13 03:49:36 -08:00
//This needs to call the callback function if one has been provided and rest the timer
ISR ( TIMER3_OVF_vect )
{
2013-02-14 04:19:34 -08:00
if ( schedule1Active = = 1 ) //Check to see if this schedule is turn on
2013-02-13 03:49:36 -08:00
{
2013-02-14 04:19:34 -08:00
schedule1StartCallback ( ) ; //Replace with user provided callback
schedule1Active = 2 ; //Turn off the callback
2013-02-14 04:43:18 -08:00
TCNT3 = 65536 - ( schedule1Duration / 16 ) ;
2013-02-14 04:19:34 -08:00
}
else if ( schedule1Active = = 2 )
{
schedule1EndCallback ( ) ;
schedule1Active = 0 ; //Turn off the callback
TCNT3 = 0 ; //Reset Timer to 0 out of 255
2013-02-13 03:49:36 -08:00
}
TIFR3 = 0x00 ; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
2013-02-13 22:34:29 -08:00
}
//AS above for schedule2
ISR ( TIMER4_OVF_vect )
{
2013-02-14 04:19:34 -08:00
if ( schedule2Active = = 1 ) //A value of 1 means call the start callback
2013-02-13 22:34:29 -08:00
{
2013-02-14 04:19:34 -08:00
schedule2StartCallback ( ) ;
schedule2Active = 2 ; //Set to call the end callback on the next run
TCNT4 = 65536 - ( schedule2Duration / 16 ) ;
}
else if ( schedule2Active = = 2 )
{
schedule2EndCallback ( ) ;
schedule2Active = 0 ; //Turn off the callback
TCNT4 = 0 ; //Reset Timer to 0 out of 255
2013-02-13 22:34:29 -08:00
}
2013-02-14 04:19:34 -08:00
TIFR4 = 0x00 ; //Timer2 INT Flag Reg: Clear Timer Overflow Flag
2013-02-13 03:49:36 -08:00
}