2021-06-21 22:30:52 -07:00
/** @file
Injector and Ignition ( on / off ) scheduling ( structs ) .
2017-02-07 20:40:44 -08:00
This scheduler is designed to maintain 2 schedules for use by the fuel and ignition systems .
2021-06-21 22:30:52 -07:00
It functions by waiting for the overflow vectors from each of the timers in use to overflow , which triggers an interrupt .
# # Technical
Currently I am prescaling the 16 - bit timers to 256 for injection and 64 for ignition .
This means that the counter increments every 16u s ( injection ) / 4u S ( ignition ) and will overflow every 1048576u S .
Max Period = ( Prescale ) * ( 1 / Frequency ) * ( 2 ^ 17 )
For more details see https : //playground.arduino.cc/Code/Timer1/ (OLD: http://playground.arduino.cc/code/timer1 ).
This means that the precision of the scheduler is :
- 16u S ( + / - 8u S of target ) for fuel
- 4u S ( + / - 2u S ) for ignition
# # Features
2013-02-13 03:49:36 -08:00
2021-06-21 22:30:52 -07:00
This differs from most other schedulers in that its calls are non - recurring ( ie when you schedule an event at a certain time and once it has occurred ,
2022-04-10 17:49:58 -07:00
it will not reoccur unless you explicitly ask / re - register for it ) .
2021-06-21 22:30:52 -07:00
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 .
2013-02-13 03:49:36 -08:00
2021-06-21 22:30:52 -07:00
# # Timer identification
2013-02-13 03:49:36 -08:00
2021-06-21 22:30:52 -07:00
Arduino timers usage for injection and ignition schedules :
- timer3 is used for schedule 1 ( ? ) ( fuel 1 , 2 , 3 , 4 ign 7 , 8 )
- timer4 is used for schedule 2 ( ? ) ( fuel 5 , 6 ign 4 , 5 , 6 )
- timer5 is used . . . ( fuel 7 , 8 , ign 1 , 2 , 3 )
2013-02-13 13:51:29 -08:00
2021-06-21 22:30:52 -07:00
Timers 3 , 4 and 5 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
*/
2015-02-14 05:11:43 -08:00
# ifndef SCHEDULER_H
# define SCHEDULER_H
2013-02-13 03:49:36 -08:00
2020-02-03 14:19:43 -08:00
# include "globals.h"
2018-09-04 00:07:21 -07:00
# define USE_IGN_REFRESH
2017-12-04 14:15:17 -08:00
# define IGNITION_REFRESH_THRESHOLD 30 //Time in uS that the refresh functions will check to ensure there is enough time before changing the end compare
2016-10-09 06:06:52 -07:00
2023-05-21 20:37:40 -07:00
# define DWELL_AVERAGE_ALPHA 30
# define DWELL_AVERAGE(input) (((long)input * (256 - DWELL_AVERAGE_ALPHA) + ((long)currentStatus.actualDwell * DWELL_AVERAGE_ALPHA))) >> 8
//#define DWELL_AVERAGE(input) (currentStatus.dwell) //Can be use to disable the above for testing
2022-11-05 15:43:29 -07:00
void initialiseSchedulers ( void ) ;
void beginInjectorPriming ( void ) ;
2023-10-06 14:25:26 -07:00
2018-06-05 19:15:07 -07:00
void setFuelSchedule1 ( unsigned long timeout , unsigned long duration ) ;
void setFuelSchedule2 ( unsigned long timeout , unsigned long duration ) ;
void setFuelSchedule3 ( unsigned long timeout , unsigned long duration ) ;
void setFuelSchedule4 ( unsigned long timeout , unsigned long duration ) ;
2023-10-06 14:25:26 -07:00
# if INJ_CHANNELS >= 5
2019-11-11 22:10:32 -08:00
void setFuelSchedule5 ( unsigned long timeout , unsigned long duration ) ;
2023-10-06 14:25:26 -07:00
# endif
# if INJ_CHANNELS >= 6
2018-06-05 19:15:07 -07:00
void setFuelSchedule6 ( unsigned long timeout , unsigned long duration ) ;
2023-10-06 14:25:26 -07:00
# endif
# if INJ_CHANNELS >= 7
2018-06-05 19:15:07 -07:00
void setFuelSchedule7 ( unsigned long timeout , unsigned long duration ) ;
2023-10-06 14:25:26 -07:00
# endif
# if INJ_CHANNELS >= 8
2018-06-05 19:15:07 -07:00
void setFuelSchedule8 ( unsigned long timeout , unsigned long duration ) ;
2023-10-06 14:25:26 -07:00
# endif
void setIgnitionSchedule1 ( unsigned long timeout , unsigned long duration ) ;
void setIgnitionSchedule2 ( unsigned long timeout , unsigned long duration ) ;
void setIgnitionSchedule3 ( unsigned long timeout , unsigned long duration ) ;
void setIgnitionSchedule4 ( unsigned long timeout , unsigned long duration ) ;
void setIgnitionSchedule5 ( unsigned long timeout , unsigned long duration ) ;
# if IGN_CHANNELS >= 6
void setIgnitionSchedule6 ( unsigned long timeout , unsigned long duration ) ;
# endif
# if IGN_CHANNELS >= 7
void setIgnitionSchedule7 ( unsigned long timeout , unsigned long duration ) ;
# endif
# if IGN_CHANNELS >= 8
void setIgnitionSchedule8 ( unsigned long timeout , unsigned long duration ) ;
# endif
2013-09-04 17:27:16 -07:00
2023-08-21 21:38:17 -07:00
void disablePendingFuelSchedule ( byte channel ) ;
void disablePendingIgnSchedule ( byte channel ) ;
2023-10-06 00:10:20 -07:00
void refreshIgnitionSchedule1 ( unsigned long timeToEnd ) ;
2017-10-24 05:31:42 -07:00
2022-06-26 17:39:14 -07:00
//The ARM cores use separate functions for their ISRs
2020-12-07 05:43:01 -08:00
# if defined(ARDUINO_ARCH_STM32) || defined(CORE_TEENSY)
2023-10-06 00:10:20 -07:00
void fuelSchedule1Interrupt ( void ) ;
void fuelSchedule2Interrupt ( void ) ;
void fuelSchedule3Interrupt ( void ) ;
void fuelSchedule4Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# if (INJ_CHANNELS >= 5)
2023-10-06 00:10:20 -07:00
void fuelSchedule5Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (INJ_CHANNELS >= 6)
2023-10-06 00:10:20 -07:00
void fuelSchedule6Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (INJ_CHANNELS >= 7)
2023-10-06 00:10:20 -07:00
void fuelSchedule7Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (INJ_CHANNELS >= 8)
2023-10-06 00:10:20 -07:00
void fuelSchedule8Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 1)
2023-10-06 00:10:20 -07:00
void ignitionSchedule1Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 2)
2023-10-06 00:10:20 -07:00
void ignitionSchedule2Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 3)
2023-10-06 00:10:20 -07:00
void ignitionSchedule3Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 4)
2023-10-06 00:10:20 -07:00
void ignitionSchedule4Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 5)
2023-10-06 00:10:20 -07:00
void ignitionSchedule5Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 6)
2023-10-06 00:10:20 -07:00
void ignitionSchedule6Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 7)
2023-10-06 00:10:20 -07:00
void ignitionSchedule7Interrupt ( void ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 8)
2023-10-06 00:10:20 -07:00
void ignitionSchedule8Interrupt ( void ) ;
2017-04-21 07:30:13 -07:00
# endif
2018-01-27 03:14:11 -08:00
# endif
2021-06-21 22:30:52 -07:00
/** Schedule statuses.
* - OFF - Schedule turned off and there is no scheduled plan
* - PENDING - There ' s a scheduled plan , but is has not started to run yet
* - STAGED - ( ? ? ? , Not used )
* - RUNNING - Schedule is currently running
*/
2021-10-22 15:04:31 -07:00
enum ScheduleStatus { OFF , PENDING , STAGED , RUNNING } ; //The statuses that a schedule can have
2021-06-21 22:30:52 -07:00
/** Ignition schedule.
*/
2023-10-06 14:25:26 -07:00
struct IgnitionSchedule {
// Deduce the real types of the counter and compare registers.
// COMPARE_TYPE is NOT the same - it's just an integer type wide enough to
// store 16-bit counter/compare calculation results.
using counter_t = decltype ( IGN1_COUNTER ) ;
using compare_t = decltype ( IGN1_COMPARE ) ;
IgnitionSchedule ( counter_t & counter , compare_t & compare ,
void ( & _pTimerDisable ) ( ) , void ( & _pTimerEnable ) ( ) )
: counter ( counter )
, compare ( compare )
, pTimerDisable ( _pTimerDisable )
, pTimerEnable ( _pTimerEnable )
{
}
2021-06-21 22:30:52 -07:00
volatile unsigned long duration ; ///< Scheduled duration (uS ?)
volatile ScheduleStatus Status ; ///< Schedule status: OFF, PENDING, STAGED, RUNNING
2023-10-06 14:25:26 -07:00
void ( * pStartCallback ) ( void ) ; ///< Start Callback function for schedule
void ( * pEndCallback ) ( void ) ; ///< End Callback function for schedule
2019-04-21 07:23:44 -07:00
volatile unsigned long startTime ; /**< The system time (in uS) that the schedule started, used by the overdwell protection in timers.ino */
2021-06-21 22:30:52 -07:00
volatile COMPARE_TYPE startCompare ; ///< The counter value of the timer when this will start
volatile COMPARE_TYPE endCompare ; ///< The counter value of the timer when this will end
2017-08-02 18:51:07 -07:00
2021-11-11 20:11:42 -08:00
COMPARE_TYPE nextStartCompare ; ///< Planned start of next schedule (when current schedule is RUNNING)
COMPARE_TYPE nextEndCompare ; ///< Planned end of next schedule (when current schedule is RUNNING)
2021-06-21 22:30:52 -07:00
volatile bool hasNextSchedule = false ; ///< Enable flag for planned next schedule (when current schedule is RUNNING)
2018-08-13 19:46:39 -07:00
volatile bool endScheduleSetByDecoder = false ;
2023-10-06 14:25:26 -07:00
counter_t & counter ; // Reference to the counter register. E.g. TCNT3
compare_t & compare ; // Reference to the compare register. E.g. OCR3A
void ( & pTimerDisable ) ( ) ; // Reference to the timer disable function
void ( & pTimerEnable ) ( ) ; // Reference to the timer enable function
2019-11-11 20:04:36 -08:00
} ;
2023-10-06 14:25:26 -07:00
2021-06-21 22:30:52 -07:00
/** Fuel injection schedule.
* Fuel schedules don ' t use the callback pointers , or the startTime / endScheduleSetByDecoder variables .
* They are removed in this struct to save RAM .
*/
2019-11-11 20:04:36 -08:00
struct FuelSchedule {
2023-10-06 14:25:26 -07:00
// Deduce the real types of the counter and compare registers.
// COMPARE_TYPE is NOT the same - it's just an integer type wide enough to
// store 16-bit counter/compare calculation results.
using counter_t = decltype ( FUEL1_COUNTER ) ;
using compare_t = decltype ( FUEL1_COMPARE ) ;
FuelSchedule ( counter_t & counter , compare_t & compare ,
void ( & _pTimerDisable ) ( ) , void ( & _pTimerEnable ) ( ) )
: counter ( counter )
, compare ( compare )
, pTimerDisable ( _pTimerDisable )
, pTimerEnable ( _pTimerEnable )
{
}
2021-06-21 22:30:52 -07:00
volatile unsigned long duration ; ///< Scheduled duration (uS ?)
volatile ScheduleStatus Status ; ///< Schedule status: OFF, PENDING, STAGED, RUNNING
volatile COMPARE_TYPE startCompare ; ///< The counter value of the timer when this will start
volatile COMPARE_TYPE endCompare ; ///< The counter value of the timer when this will end
2023-10-06 14:25:26 -07:00
void ( * pStartFunction ) ( void ) ;
void ( * pEndFunction ) ( void ) ;
2021-11-11 20:11:42 -08:00
COMPARE_TYPE nextStartCompare ;
COMPARE_TYPE nextEndCompare ;
2019-11-11 20:04:36 -08:00
volatile bool hasNextSchedule = false ;
2016-06-26 20:46:29 -07:00
2023-10-06 14:25:26 -07:00
counter_t & counter ; // Reference to the counter register. E.g. TCNT3
compare_t & compare ; // Reference to the compare register. E.g. OCR3A
void ( & pTimerDisable ) ( ) ; // Reference to the timer disable function
void ( & pTimerEnable ) ( ) ; // Reference to the timer enable function
} ;
2013-09-04 17:27:16 -07:00
2020-01-29 21:17:20 -08:00
extern FuelSchedule fuelSchedule1 ;
extern FuelSchedule fuelSchedule2 ;
extern FuelSchedule fuelSchedule3 ;
extern FuelSchedule fuelSchedule4 ;
2023-10-06 14:25:26 -07:00
# if INJ_CHANNELS >= 5
2020-01-29 21:17:20 -08:00
extern FuelSchedule fuelSchedule5 ;
2023-10-06 14:25:26 -07:00
# endif
# if INJ_CHANNELS >= 6
2020-01-29 21:17:20 -08:00
extern FuelSchedule fuelSchedule6 ;
2023-10-06 14:25:26 -07:00
# endif
# if INJ_CHANNELS >= 7
2020-01-29 21:17:20 -08:00
extern FuelSchedule fuelSchedule7 ;
2023-10-06 14:25:26 -07:00
# endif
# if INJ_CHANNELS >= 8
2020-01-29 21:17:20 -08:00
extern FuelSchedule fuelSchedule8 ;
2023-10-06 14:25:26 -07:00
# endif
2020-01-29 21:17:20 -08:00
2023-10-06 14:25:26 -07:00
extern IgnitionSchedule ignitionSchedule1 ;
extern IgnitionSchedule ignitionSchedule2 ;
extern IgnitionSchedule ignitionSchedule3 ;
extern IgnitionSchedule ignitionSchedule4 ;
extern IgnitionSchedule ignitionSchedule5 ;
# if IGN_CHANNELS >= 6
extern IgnitionSchedule ignitionSchedule6 ;
# endif
# if IGN_CHANNELS >= 7
extern IgnitionSchedule ignitionSchedule7 ;
# endif
# if IGN_CHANNELS >= 8
extern IgnitionSchedule ignitionSchedule8 ;
# endif
2015-02-14 05:11:43 -08:00
2017-08-02 19:29:05 -07:00
# endif // SCHEDULER_H