2013-02-13 03:49:36 -08:00
/*
2017-02-07 20:40:44 -08:00
This scheduler is designed to maintain 2 schedules for use by the fuel and ignition systems .
2013-02-13 03:49:36 -08:00
It functions by waiting for the overflow vectors from each of the timers in use to overflow , which triggers an interrupt
//Technical
2015-02-06 02:19:16 -08:00
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
2013-02-13 03:49:36 -08:00
Max Period = ( Prescale ) * ( 1 / Frequency ) * ( 2 ^ 17 )
( See http : //playground.arduino.cc/code/timer1)
2015-02-06 02:19:16 -08:00
This means that the precision of the scheduler is 16u S ( + / - 8u S of target ) for fuel and 4u S ( + / - 2u S ) for ignition
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
*/
2015-02-14 05:11:43 -08:00
# ifndef SCHEDULER_H
# define SCHEDULER_H
2013-02-13 03:49:36 -08:00
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
2017-08-02 18:51:07 -07:00
# if defined(CORE_AVR)
2017-02-07 20:40:44 -08:00
# include <avr/interrupt.h>
# include <avr/io.h>
2016-10-09 06:06:52 -07:00
//Refer to http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/include/avr/iomxx0_1.h?root=avr-libc&view=markup
# define FUEL1_COUNTER TCNT3
# define FUEL2_COUNTER TCNT3
# define FUEL3_COUNTER TCNT3
# define FUEL4_COUNTER TCNT4
2017-08-02 18:51:07 -07:00
# define FUEL5_COUNTER TCNT3
2018-01-21 17:21:33 -08:00
//The following are for the additional dynamic modes and share the counter and compares with the ignition
# define FUEL6_COUNTER TCNT4 //Takes off ignition 4
# define FUEL7_COUNTER TCNT5
# define FUEL8_COUNTER TCNT5
2017-02-07 20:40:44 -08:00
2016-10-09 06:06:52 -07:00
# define IGN1_COUNTER TCNT5
# define IGN2_COUNTER TCNT5
# define IGN3_COUNTER TCNT5
# define IGN4_COUNTER TCNT4
2016-12-28 03:52:00 -08:00
# define IGN5_COUNTER TCNT1
2018-01-21 17:21:33 -08:00
//The following are for the additional dynamic modes and share the counter and compares with the injectors
# define IGN6_COUNTER TCNT4 //Replaces injector 4
# define IGN7_COUNTER TCNT3 //Replaces injector 3
# define IGN8_COUNTER TCNT3 //Replaces injector 2
2016-10-09 06:06:52 -07:00
# define FUEL1_COMPARE OCR3A
# define FUEL2_COMPARE OCR3B
# define FUEL3_COMPARE OCR3C
# define FUEL4_COMPARE OCR4B
2017-08-02 18:51:07 -07:00
# define FUEL5_COMPARE OCR3A //Shared with FUEL1
2018-01-21 17:21:33 -08:00
//The following are for the additional dynamic modes and share the counter and compares with the ignition
# define FUEL6_COMPARE OCR4A //Replaces ignition4
# define FUEL7_COMPARE OCR5C //Replaces ignition3
# define FUEL8_COMPARE OCR5B //Replaces ignition2
2017-02-07 20:40:44 -08:00
2016-10-09 06:06:52 -07:00
# define IGN1_COMPARE OCR5A
# define IGN2_COMPARE OCR5B
# define IGN3_COMPARE OCR5C
# define IGN4_COMPARE OCR4A
2016-12-28 03:52:00 -08:00
# define IGN5_COMPARE OCR1C
2018-01-21 17:21:33 -08:00
//The following are for the additional dynamic modes and share the counter and compares with the injectors
# define IGN6_COMPARE OCR4B //Replaces injector 4
# define IGN7_COMPARE OCR3C //Replaces injector 3
# define IGN8_COMPARE OCR3B //Replaces injector 2
2016-10-09 06:06:52 -07:00
# define FUEL1_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3A) //Turn on the A compare unit (ie turn on the interrupt)
# define FUEL2_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3B) //Turn on the B compare unit (ie turn on the interrupt)
# define FUEL3_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3C) //Turn on the C compare unit (ie turn on the interrupt)
# define FUEL4_TIMER_ENABLE() TIMSK4 |= (1 << OCIE4B) //Turn on the B compare unit (ie turn on the interrupt)
2018-01-21 17:21:33 -08:00
# define FUEL5_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3B) //
# define FUEL6_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3B) //
# define FUEL7_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3C) //
# define FUEL8_TIMER_ENABLE() TIMSK4 |= (1 << OCIE4B) //
2016-10-09 06:06:52 -07:00
2016-10-09 22:58:19 -07:00
# define FUEL1_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3A); //Turn off this output compare unit
# define FUEL2_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3B); //Turn off this output compare unit
# define FUEL3_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3C); //Turn off this output compare unit
# define FUEL4_TIMER_DISABLE() TIMSK4 &= ~(1 << OCIE4B); //Turn off this output compare unit
2018-01-21 17:21:33 -08:00
# define FUEL5_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3A); //
# define FUEL6_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3B); //
# define FUEL7_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3C); //
# define FUEL8_TIMER_DISABLE() TIMSK4 &= ~(1 << OCIE4B); //
2016-10-09 22:58:19 -07:00
2016-10-09 06:06:52 -07:00
# define IGN1_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5A) //Turn on the A compare unit (ie turn on the interrupt)
# define IGN2_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5B) //Turn on the B compare unit (ie turn on the interrupt)
# define IGN3_TIMER_ENABLE() TIMSK5 |= (1 << OCIE5C) //Turn on the C compare unit (ie turn on the interrupt)
# define IGN4_TIMER_ENABLE() TIMSK4 |= (1 << OCIE4A) //Turn on the A compare unit (ie turn on the interrupt)
2016-12-28 03:52:00 -08:00
# define IGN5_TIMER_ENABLE() TIMSK1 |= (1 << OCIE1C) //Turn on the A compare unit (ie turn on the interrupt)
2018-01-21 17:21:33 -08:00
# define IGN6_TIMER_ENABLE() TIMSK4 |= (1 << OCIE4B) //Replaces injector 4
# define IGN7_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3C) //Replaces injector 3
# define IGN8_TIMER_ENABLE() TIMSK3 |= (1 << OCIE3B) //Replaces injector 2
2016-10-09 06:06:52 -07:00
2017-02-07 20:40:44 -08:00
# define IGN1_TIMER_DISABLE() TIMSK5 &= ~(1 << OCIE5A) //Turn off this output compare unit
2016-10-09 06:06:52 -07:00
# define IGN2_TIMER_DISABLE() TIMSK5 &= ~(1 << OCIE5B) //Turn off this output compare unit
# define IGN3_TIMER_DISABLE() TIMSK5 &= ~(1 << OCIE5C) //Turn off this output compare unit
2016-10-09 22:58:19 -07:00
# define IGN4_TIMER_DISABLE() TIMSK4 &= ~(1 << OCIE4A) //Turn off this output compare unit
2016-12-28 03:52:00 -08:00
# define IGN5_TIMER_DISABLE() TIMSK1 &= ~(1 << OCIE1C) //Turn off this output compare unit
2018-01-21 17:21:33 -08:00
# define IGN6_TIMER_DISABLE() TIMSK4 &= ~(1 << OCIE4B) //Replaces injector 4
# define IGN7_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3C) //Replaces injector 3
# define IGN8_TIMER_DISABLE() TIMSK3 &= ~(1 << OCIE3B) //Replaces injector 2
2016-10-09 06:06:52 -07:00
2017-10-24 05:31:42 -07:00
# define MAX_TIMER_PERIOD 262140UL //The longest period of time (in uS) that the timer can permit (IN this case it is 65535 * 4, as each timer tick is 4uS)
# define MAX_TIMER_PERIOD_SLOW 1048560UL //The longest period of time (in uS) that the timer can permit (IN this case it is 65535 * 16, as each timer tick is 16uS)
2016-11-26 03:10:41 -08:00
# define uS_TO_TIMER_COMPARE(uS1) (uS1 >> 2) //Converts a given number of uS into the required number of timer ticks until that time has passed
2017-03-29 00:11:16 -07:00
//This is a hack until I make all the AVR timers run at the same speed
# define uS_TO_TIMER_COMPARE_SLOW(uS1) (uS1 >> 4)
2016-11-22 16:51:12 -08:00
2017-02-07 20:40:44 -08:00
# elif defined(CORE_TEENSY)
2016-10-09 06:06:52 -07:00
//http://shawnhymel.com/661/learning-the-teensy-lc-interrupt-service-routines/
# define FUEL1_COUNTER FTM0_CNT
# define FUEL2_COUNTER FTM0_CNT
# define FUEL3_COUNTER FTM0_CNT
# define FUEL4_COUNTER FTM0_CNT
2017-02-20 02:34:28 -08:00
# define FUEL5_COUNTER FTM3_CNT
# define FUEL6_COUNTER FTM3_CNT
# define FUEL7_COUNTER FTM3_CNT
# define FUEL8_COUNTER FTM3_CNT
2016-10-09 06:06:52 -07:00
# define IGN1_COUNTER FTM0_CNT
# define IGN2_COUNTER FTM0_CNT
# define IGN3_COUNTER FTM0_CNT
# define IGN4_COUNTER FTM0_CNT
2017-02-20 02:34:28 -08:00
# define IGN5_COUNTER FTM3_CNT
# define IGN6_COUNTER FTM3_CNT
# define IGN7_COUNTER FTM3_CNT
# define IGN8_COUNTER FTM3_CNT
2016-10-09 06:06:52 -07:00
# define FUEL1_COMPARE FTM0_C0V
# define FUEL2_COMPARE FTM0_C1V
# define FUEL3_COMPARE FTM0_C2V
# define FUEL4_COMPARE FTM0_C3V
2017-02-20 02:34:28 -08:00
# define FUEL5_COMPARE FTM3_C0V
# define FUEL6_COMPARE FTM3_C1V
# define FUEL7_COMPARE FTM3_C2V
# define FUEL8_COMPARE FTM3_C3V
2016-10-09 06:06:52 -07:00
# define IGN1_COMPARE FTM0_C4V
# define IGN2_COMPARE FTM0_C5V
# define IGN3_COMPARE FTM0_C6V
# define IGN4_COMPARE FTM0_C7V
2017-02-20 02:34:28 -08:00
# define IGN5_COMPARE FTM3_C4V
# define IGN6_COMPARE FTM3_C5V
# define IGN7_COMPARE FTM3_C6V
# define IGN8_COMPARE FTM3_C7V
2016-10-09 06:06:52 -07:00
2016-11-22 16:51:12 -08:00
# define FUEL1_TIMER_ENABLE() FTM0_C0SC |= FTM_CSC_CHIE //Write 1 to the CHIE (Channel Interrupt Enable) bit of channel 0 Status/Control
# define FUEL2_TIMER_ENABLE() FTM0_C1SC |= FTM_CSC_CHIE
# define FUEL3_TIMER_ENABLE() FTM0_C2SC |= FTM_CSC_CHIE
# define FUEL4_TIMER_ENABLE() FTM0_C3SC |= FTM_CSC_CHIE
2017-02-20 02:34:28 -08:00
# define FUEL5_TIMER_ENABLE() FTM3_C0SC |= FTM_CSC_CHIE
# define FUEL6_TIMER_ENABLE() FTM3_C1SC |= FTM_CSC_CHIE
# define FUEL7_TIMER_ENABLE() FTM3_C2SC |= FTM_CSC_CHIE
# define FUEL8_TIMER_ENABLE() FTM3_C3SC |= FTM_CSC_CHIE
2016-11-22 16:51:12 -08:00
# define FUEL1_TIMER_DISABLE() FTM0_C0SC &= ~FTM_CSC_CHIE //Write 0 to the CHIE (Channel Interrupt Enable) bit of channel 0 Status/Control
# define FUEL2_TIMER_DISABLE() FTM0_C1SC &= ~FTM_CSC_CHIE
# define FUEL3_TIMER_DISABLE() FTM0_C2SC &= ~FTM_CSC_CHIE
# define FUEL4_TIMER_DISABLE() FTM0_C3SC &= ~FTM_CSC_CHIE
2017-02-20 02:34:28 -08:00
# define FUEL5_TIMER_DISABLE() FTM3_C0SC &= ~FTM_CSC_CHIE //Write 0 to the CHIE (Channel Interrupt Enable) bit of channel 0 Status/Control
# define FUEL6_TIMER_DISABLE() FTM3_C1SC &= ~FTM_CSC_CHIE
# define FUEL7_TIMER_DISABLE() FTM3_C2SC &= ~FTM_CSC_CHIE
# define FUEL8_TIMER_DISABLE() FTM3_C3SC &= ~FTM_CSC_CHIE
2016-11-22 16:51:12 -08:00
# define IGN1_TIMER_ENABLE() FTM0_C4SC |= FTM_CSC_CHIE
# define IGN2_TIMER_ENABLE() FTM0_C5SC |= FTM_CSC_CHIE
# define IGN3_TIMER_ENABLE() FTM0_C6SC |= FTM_CSC_CHIE
# define IGN4_TIMER_ENABLE() FTM0_C7SC |= FTM_CSC_CHIE
2017-02-20 02:34:28 -08:00
# define IGN5_TIMER_ENABLE() FTM3_C4SC |= FTM_CSC_CHIE
# define IGN6_TIMER_ENABLE() FTM3_C5SC |= FTM_CSC_CHIE
# define IGN7_TIMER_ENABLE() FTM3_C6SC |= FTM_CSC_CHIE
# define IGN8_TIMER_ENABLE() FTM3_C7SC |= FTM_CSC_CHIE
2016-11-22 16:51:12 -08:00
# define IGN1_TIMER_DISABLE() FTM0_C4SC &= ~FTM_CSC_CHIE
# define IGN2_TIMER_DISABLE() FTM0_C5SC &= ~FTM_CSC_CHIE
# define IGN3_TIMER_DISABLE() FTM0_C6SC &= ~FTM_CSC_CHIE
# define IGN4_TIMER_DISABLE() FTM0_C7SC &= ~FTM_CSC_CHIE
2017-02-20 02:34:28 -08:00
# define IGN5_TIMER_DISABLE() FTM3_C4SC &= ~FTM_CSC_CHIE
# define IGN6_TIMER_DISABLE() FTM3_C5SC &= ~FTM_CSC_CHIE
# define IGN7_TIMER_DISABLE() FTM3_C6SC &= ~FTM_CSC_CHIE
# define IGN8_TIMER_DISABLE() FTM3_C7SC &= ~FTM_CSC_CHIE
2016-11-22 16:51:12 -08:00
# define MAX_TIMER_PERIOD 139808 // 2.13333333uS * 65535
2017-10-18 23:02:43 -07:00
# define MAX_TIMER_PERIOD_SLOW 139808
2017-02-07 20:40:44 -08:00
# define uS_TO_TIMER_COMPARE(uS) ((uS * 15) >> 5) //Converts a given number of uS into the required number of timer ticks until that time has passed.
2017-03-29 00:11:16 -07:00
//Hack compatibility with AVR timers that run at different speeds
# define uS_TO_TIMER_COMPARE_SLOW(uS) ((uS * 15) >> 5)
2017-02-07 20:40:44 -08:00
2017-04-21 07:30:13 -07:00
# elif defined(CORE_STM32)
# define MAX_TIMER_PERIOD 131070 //The longest period of time (in uS) that the timer can permit (IN this case it is 65535 * 2, as each timer tick is 2uS)
2017-10-18 23:02:43 -07:00
# define MAX_TIMER_PERIOD_SLOW 131070 //The longest period of time (in uS) that the timer can permit (IN this case it is 65535 * 2, as each timer tick is 2uS)
2017-04-21 07:30:13 -07:00
# define uS_TO_TIMER_COMPARE(uS) (uS >> 1) //Converts a given number of uS into the required number of timer ticks until that time has passed.
# define uS_TO_TIMER_COMPARE_SLOW(uS) (uS >> 1) //Converts a given number of uS into the required number of timer ticks until that time has passed.
2017-08-03 20:13:32 -07:00
# if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
2017-08-02 19:29:05 -07:00
# include "HardwareTimer.h"
# define FUEL1_COUNTER (TIM2)->CNT
# define FUEL2_COUNTER (TIM2)->CNT
# define FUEL3_COUNTER (TIM2)->CNT
# define FUEL4_COUNTER (TIM2)->CNT
2018-01-23 21:23:15 -08:00
# define FUEL5_COUNTER (TIM4)->CNT
# define FUEL6_COUNTER (TIM4)->CNT
# define FUEL7_COUNTER (TIM4)->CNT
# define FUEL8_COUNTER (TIM4)->CNT
2017-08-02 19:29:05 -07:00
# define IGN1_COUNTER (TIM3)->CNT
# define IGN2_COUNTER (TIM3)->CNT
# define IGN3_COUNTER (TIM3)->CNT
# define IGN4_COUNTER (TIM3)->CNT
2018-01-23 21:23:15 -08:00
# define IGN5_COUNTER (TIM4)->CNT
# define IGN6_COUNTER (TIM4)->CNT
# define IGN7_COUNTER (TIM4)->CNT
# define IGN8_COUNTER (TIM4)->CNT
2017-08-02 19:29:05 -07:00
# define FUEL1_COMPARE (TIM2)->CCR1
# define FUEL2_COMPARE (TIM2)->CCR2
# define FUEL3_COMPARE (TIM2)->CCR3
# define FUEL4_COMPARE (TIM2)->CCR4
2018-01-23 21:23:15 -08:00
# define FUEL5_COMPARE (TIM4)->CCR1
# define FUEL6_COMPARE (TIM4)->CCR2
# define FUEL7_COMPARE (TIM4)->CCR3
# define FUEL8_COMPARE (TIM4)->CCR4
2017-08-02 19:29:05 -07:00
# define IGN1_COMPARE (TIM3)->CCR1
# define IGN2_COMPARE (TIM3)->CCR2
# define IGN3_COMPARE (TIM3)->CCR3
# define IGN4_COMPARE (TIM3)->CCR4
2018-01-23 21:23:15 -08:00
# define IGN5_COMPARE (TIM4)->CCR1
# define IGN6_COMPARE (TIM4)->CCR2
# define IGN7_COMPARE (TIM4)->CCR3
# define IGN8_COMPARE (TIM4)->CCR4
2017-08-02 19:29:05 -07:00
//https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
# define FUEL1_TIMER_ENABLE() (TIM2)->CCER |= TIM_CCER_CC1E
# define FUEL2_TIMER_ENABLE() (TIM2)->CCER |= TIM_CCER_CC2E
# define FUEL3_TIMER_ENABLE() (TIM2)->CCER |= TIM_CCER_CC3E
# define FUEL4_TIMER_ENABLE() (TIM2)->CCER |= TIM_CCER_CC4E
2018-01-23 21:23:15 -08:00
# define FUEL5_TIMER_ENABLE() (TIM4)->CCER |= TIM_CCER_CC1E
# define FUEL6_TIMER_ENABLE() (TIM4)->CCER |= TIM_CCER_CC2E
# define FUEL7_TIMER_ENABLE() (TIM4)->CCER |= TIM_CCER_CC3E
# define FUEL8_TIMER_ENABLE() (TIM4)->CCER |= TIM_CCER_CC4E
2017-08-02 19:29:05 -07:00
# define IGN1_TIMER_ENABLE() (TIM3)->CCER |= TIM_CCER_CC1E
# define IGN2_TIMER_ENABLE() (TIM3)->CCER |= TIM_CCER_CC2E
# define IGN3_TIMER_ENABLE() (TIM3)->CCER |= TIM_CCER_CC3E
# define IGN4_TIMER_ENABLE() (TIM3)->CCER |= TIM_CCER_CC4E
# define IGN5_TIMER_ENABLE() (TIM1)->CCER |= TIM_CCER_CC1E
# define FUEL1_TIMER_DISABLE() (TIM2)->CCER &= ~TIM_CCER_CC1E
# define FUEL2_TIMER_DISABLE() (TIM2)->CCER &= ~TIM_CCER_CC2E
# define FUEL3_TIMER_DISABLE() (TIM2)->CCER &= ~TIM_CCER_CC3E
# define FUEL4_TIMER_DISABLE() (TIM2)->CCER &= ~TIM_CCER_CC4E
# define IGN1_TIMER_DISABLE() (TIM3)->CCER &= ~TIM_CCER_CC1E
# define IGN2_TIMER_DISABLE() (TIM3)->CCER &= ~TIM_CCER_CC2E
# define IGN3_TIMER_DISABLE() (TIM3)->CCER &= ~TIM_CCER_CC3E
# define IGN4_TIMER_DISABLE() (TIM3)->CCER &= ~TIM_CCER_CC4E
# define IGN5_TIMER_DISABLE() (TIM1)->CCER &= ~TIM_CCER_CC1E
2017-08-03 20:13:32 -07:00
# else //libmaple core aka STM32DUINO
2017-08-02 19:29:05 -07:00
# define FUEL1_COUNTER (TIMER2->regs).gen->CNT
# define FUEL2_COUNTER (TIMER2->regs).gen->CNT
# define FUEL3_COUNTER (TIMER2->regs).gen->CNT
# define FUEL4_COUNTER (TIMER2->regs).gen->CNT
2018-01-23 21:23:15 -08:00
# define FUEL5_COUNTER (TIMER4->regs).gen->CNT
# define FUEL6_COUNTER (TIMER4->regs).gen->CNT
# define FUEL7_COUNTER (TIMER4->regs).gen->CNT
# define FUEL8_COUNTER (TIMER4->regs).gen->CNT
2017-08-02 19:29:05 -07:00
# define IGN1_COUNTER (TIMER3->regs).gen->CNT
# define IGN2_COUNTER (TIMER3->regs).gen->CNT
# define IGN3_COUNTER (TIMER3->regs).gen->CNT
# define IGN4_COUNTER (TIMER3->regs).gen->CNT
2018-01-23 21:23:15 -08:00
# define IGN5_COUNTER (TIMER4->regs).gen->CNT
# define IGN6_COUNTER (TIMER4->regs).gen->CNT
# define IGN7_COUNTER (TIMER4->regs).gen->CNT
# define IGN8_COUNTER (TIMER4->regs).gen->CNT
2017-08-02 19:29:05 -07:00
# define FUEL1_COMPARE (TIMER2->regs).gen->CCR1
# define FUEL2_COMPARE (TIMER2->regs).gen->CCR2
# define FUEL3_COMPARE (TIMER2->regs).gen->CCR3
# define FUEL4_COMPARE (TIMER2->regs).gen->CCR4
2018-01-23 21:23:15 -08:00
# define FUEL5_COMPARE (TIMER4->regs).gen->CCR1
# define FUEL6_COMPARE (TIMER4->regs).gen->CCR2
# define FUEL7_COMPARE (TIMER4->regs).gen->CCR3
# define FUEL8_COMPARE (TIMER4->regs).gen->CCR4
2017-08-02 19:29:05 -07:00
# define IGN1_COMPARE (TIMER3->regs).gen->CCR1
# define IGN2_COMPARE (TIMER3->regs).gen->CCR2
# define IGN3_COMPARE (TIMER3->regs).gen->CCR3
# define IGN4_COMPARE (TIMER3->regs).gen->CCR4
2018-01-23 21:23:15 -08:00
# define IGN5_COMPARE (TIMER4->regs).gen->CCR1
# define IGN6_COMPARE (TIMER4->regs).gen->CCR2
# define IGN7_COMPARE (TIMER4->regs).gen->CCR3
# define IGN8_COMPARE (TIMER4->regs).gen->CCR4
2017-08-02 19:29:05 -07:00
//https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
# define FUEL1_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC1E
# define FUEL2_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC2E
# define FUEL3_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC3E
# define FUEL4_TIMER_ENABLE() (TIMER2->regs).gen->CCER |= TIMER_CCER_CC4E
2018-01-23 21:23:15 -08:00
# define FUEL5_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC1E
# define FUEL6_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC2E
# define FUEL7_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC3E
# define FUEL8_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC4E
2017-08-02 19:29:05 -07:00
# define IGN1_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC1E
# define IGN2_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC2E
# define IGN3_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC3E
# define IGN4_TIMER_ENABLE() (TIMER3->regs).gen->CCER |= TIMER_CCER_CC4E
2018-01-23 21:23:15 -08:00
# define IGN5_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC1E
# define IGN6_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC2E
# define IGN7_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC3E
# define IGN8_TIMER_ENABLE() (TIMER4->regs).gen->CCER |= TIMER_CCER_CC4E
2017-08-02 19:29:05 -07:00
# define FUEL1_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC1E
# define FUEL2_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC2E
# define FUEL3_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC3E
# define FUEL4_TIMER_DISABLE() (TIMER2->regs).gen->CCER &= ~TIMER_CCER_CC4E
2018-01-23 21:23:15 -08:00
# define FUEL5_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC1E
# define FUEL6_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC2E
# define FUEL7_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC3E
# define FUEL8_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC4E
2017-08-02 19:29:05 -07:00
# define IGN1_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC1E
# define IGN2_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC2E
# define IGN3_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC3E
# define IGN4_TIMER_DISABLE() (TIMER3->regs).gen->CCER &= ~TIMER_CCER_CC4E
2018-01-23 21:23:15 -08:00
# define IGN5_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC1E
# define IGN6_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC2E
# define IGN7_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC3E
# define IGN8_TIMER_DISABLE() (TIMER4->regs).gen->CCER &= ~TIMER_CCER_CC4E
2017-08-02 19:29:05 -07:00
# endif
2016-10-09 06:06:52 -07:00
# endif
2013-09-04 17:27:16 -07:00
void initialiseSchedulers ( ) ;
void setFuelSchedule1 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setFuelSchedule2 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
2013-11-13 22:17:58 -08:00
void setFuelSchedule3 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setFuelSchedule4 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
2016-06-26 20:46:29 -07:00
void setFuelSchedule5 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setFuelSchedule6 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setFuelSchedule7 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setFuelSchedule8 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
2013-09-04 17:27:16 -07:00
void setIgnitionSchedule1 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setIgnitionSchedule2 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
2013-11-13 22:17:58 -08:00
void setIgnitionSchedule3 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setIgnitionSchedule4 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
2016-06-26 20:46:29 -07:00
void setIgnitionSchedule5 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setIgnitionSchedule6 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setIgnitionSchedule7 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
void setIgnitionSchedule8 ( void ( * startCallback ) ( ) , unsigned long timeout , unsigned long duration , void ( * endCallback ) ( ) ) ;
2013-09-04 17:27:16 -07:00
2017-10-24 05:31:42 -07:00
static inline void refreshIgnitionSchedule1 ( unsigned long timeToEnd ) __attribute__ ( ( always_inline ) ) ;
2018-01-23 21:23:15 -08:00
//The ARM cores use seprate functions for their ISRs
# if defined(CORE_STM32) || defined(CORE_TEENSY)
2017-04-21 07:30:13 -07:00
static inline void fuelSchedule1Interrupt ( ) ;
static inline void fuelSchedule2Interrupt ( ) ;
static inline void fuelSchedule3Interrupt ( ) ;
static inline void fuelSchedule4Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# if (INJ_CHANNELS >= 5)
2017-04-21 07:30:13 -07:00
static inline void fuelSchedule5Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (INJ_CHANNELS >= 6)
2018-01-23 21:23:15 -08:00
static inline void fuelSchedule6Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (INJ_CHANNELS >= 7)
2018-01-23 21:23:15 -08:00
static inline void fuelSchedule7Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (INJ_CHANNELS >= 8)
2018-01-23 21:23:15 -08:00
static inline void fuelSchedule8Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 1)
2017-04-21 07:30:13 -07:00
static inline void ignitionSchedule1Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 2)
2017-04-21 07:30:13 -07:00
static inline void ignitionSchedule2Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 3)
2017-04-21 07:30:13 -07:00
static inline void ignitionSchedule3Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 4)
2017-04-21 07:30:13 -07:00
static inline void ignitionSchedule4Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 5)
2017-04-21 07:30:13 -07:00
static inline void ignitionSchedule5Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 6)
2018-01-23 21:23:15 -08:00
static inline void ignitionSchedule6Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 7)
2018-01-23 21:23:15 -08:00
static inline void ignitionSchedule7Interrupt ( ) ;
2018-01-27 03:14:11 -08:00
# endif
# if (IGN_CHANNELS >= 8)
2018-01-23 21:23:15 -08:00
static inline void ignitionSchedule8Interrupt ( ) ;
2017-04-21 07:30:13 -07:00
# endif
2018-01-27 03:14:11 -08:00
# endif
2017-04-21 07:30:13 -07:00
2017-12-04 14:15:17 -08:00
enum ScheduleStatus { OFF , PENDING , STAGED , RUNNING } ; //The 3 statuses that a schedule can have
2013-09-04 17:27:16 -07:00
struct Schedule {
2013-09-08 03:01:47 -07:00
volatile unsigned long duration ;
volatile ScheduleStatus Status ;
2016-06-26 20:45:51 -07:00
volatile byte schedulesSet ; //A counter of how many times the schedule has been set
2013-09-04 17:27:16 -07:00
void ( * StartCallback ) ( ) ; //Start Callback function for schedule
void ( * EndCallback ) ( ) ; //Start Callback function for schedule
2016-06-26 20:46:29 -07:00
volatile unsigned long startTime ; //The system time (in uS) that the schedule started
2017-08-02 18:51:07 -07:00
volatile unsigned int startCompare ; //The counter value of the timer when this will start
volatile unsigned int endCompare ;
unsigned int nextStartCompare ;
unsigned int nextEndCompare ;
volatile bool hasNextSchedule = false ;
2018-01-23 21:23:15 -08:00
# if defined(CORE_AVR)
2018-01-22 21:14:03 -08:00
volatile uint16_t * counter ;
volatile uint16_t * compare ;
2018-01-23 21:23:15 -08:00
# elif defined(CORE_STM32) || defined(CORE_TEENSY)
volatile uint32_t * counter ;
volatile uint32_t * compare ;
# endif
2016-06-26 20:46:29 -07:00
} ;
2016-09-29 23:11:50 -07:00
volatile Schedule * timer3Aqueue [ 4 ] ;
2016-07-27 02:31:38 -07:00
Schedule * timer3Bqueue [ 4 ] ;
Schedule * timer3Cqueue [ 4 ] ;
2013-09-04 17:27:16 -07:00
Schedule fuelSchedule1 ;
Schedule fuelSchedule2 ;
2013-11-13 22:17:58 -08:00
Schedule fuelSchedule3 ;
Schedule fuelSchedule4 ;
2016-06-26 20:46:29 -07:00
Schedule fuelSchedule5 ;
Schedule fuelSchedule6 ;
Schedule fuelSchedule7 ;
Schedule fuelSchedule8 ;
2018-01-27 03:14:11 -08:00
2013-09-04 17:27:16 -07:00
Schedule ignitionSchedule1 ;
Schedule ignitionSchedule2 ;
2013-11-13 22:17:58 -08:00
Schedule ignitionSchedule3 ;
Schedule ignitionSchedule4 ;
2016-06-26 20:46:29 -07:00
Schedule ignitionSchedule5 ;
Schedule ignitionSchedule6 ;
Schedule ignitionSchedule7 ;
Schedule ignitionSchedule8 ;
2016-07-27 02:31:38 -07:00
Schedule nullSchedule ; //This is placed at the end of the queue. It's status will always be set to OFF and hence will never perform any action within an ISR
2016-09-29 23:11:50 -07:00
static inline unsigned int setQueue ( volatile Schedule * queue [ ] , Schedule * schedule1 , Schedule * schedule2 , unsigned int CNT )
2016-07-27 02:31:38 -07:00
{
//Create an array of all the upcoming targets, relative to the current count on the timer
unsigned int tmpQueue [ 4 ] ;
//Set the initial queue state. This order matches the tmpQueue order
2016-09-29 23:11:50 -07:00
if ( schedule1 - > Status = = OFF )
{
queue [ 0 ] = schedule2 ;
queue [ 1 ] = schedule2 ;
tmpQueue [ 0 ] = schedule2 - > startCompare - CNT ;
tmpQueue [ 1 ] = schedule2 - > endCompare - CNT ;
}
else
{
queue [ 0 ] = schedule1 ;
queue [ 1 ] = schedule1 ;
tmpQueue [ 0 ] = schedule1 - > startCompare - CNT ;
tmpQueue [ 1 ] = schedule1 - > endCompare - CNT ;
}
if ( schedule2 - > Status = = OFF )
{
queue [ 2 ] = schedule1 ;
queue [ 3 ] = schedule1 ;
tmpQueue [ 2 ] = schedule1 - > startCompare - CNT ;
2017-02-07 20:40:44 -08:00
tmpQueue [ 3 ] = schedule1 - > endCompare - CNT ;
2016-09-29 23:11:50 -07:00
}
else
{
queue [ 2 ] = schedule2 ;
2017-02-07 20:40:44 -08:00
queue [ 3 ] = schedule2 ;
2016-09-29 23:11:50 -07:00
tmpQueue [ 2 ] = schedule2 - > startCompare - CNT ;
2017-02-07 20:40:44 -08:00
tmpQueue [ 3 ] = schedule2 - > endCompare - CNT ;
2016-09-29 23:11:50 -07:00
}
2016-07-27 02:31:38 -07:00
2017-02-07 20:40:44 -08:00
//Sort the queues. Both queues are kept in sync.
2016-09-29 23:11:50 -07:00
//This implementes a sorting networking based on the Bose-Nelson sorting network
//See: http://pages.ripco.net/~jgamble/nw.html
2016-09-30 08:57:57 -07:00
# define SWAP(x,y) if(tmpQueue[y] < tmpQueue[x]) { unsigned int tmp = tmpQueue[x]; tmpQueue[x] = tmpQueue[y]; tmpQueue[y] = tmp; volatile Schedule *tmpS = queue[x]; queue[x] = queue[y]; queue[y] = tmpS; }
2016-07-27 02:31:38 -07:00
//SWAP(0, 1); //Likely not needed
//SWAP(2, 3); //Likely not needed
2016-09-29 23:11:50 -07:00
SWAP ( 0 , 2 ) ;
2016-07-27 02:31:38 -07:00
SWAP ( 1 , 3 ) ;
SWAP ( 1 , 2 ) ;
//Return the next compare time in the queue
2017-02-07 20:40:44 -08:00
return tmpQueue [ 0 ] + CNT ; //Return the
2016-07-27 02:31:38 -07:00
}
/*
2017-02-07 20:40:44 -08:00
* Moves all the Schedules in a queue forward one position .
2016-07-27 02:31:38 -07:00
* The current item ( 0 ) is discarded
* The final queue slot is set to nullSchedule to indicate that no action should be taken
*/
2016-09-29 23:11:50 -07:00
static inline unsigned int popQueue ( volatile Schedule * queue [ ] )
2016-07-27 02:31:38 -07:00
{
queue [ 0 ] = queue [ 1 ] ;
queue [ 1 ] = queue [ 2 ] ;
queue [ 2 ] = queue [ 3 ] ;
queue [ 3 ] = & nullSchedule ;
2017-08-02 18:51:07 -07:00
unsigned int returnCompare ;
if ( queue [ 0 ] - > Status = = PENDING ) { returnCompare = queue [ 0 ] - > startCompare ; }
else { returnCompare = queue [ 0 ] - > endCompare ; }
return returnCompare ;
2016-07-27 02:31:38 -07:00
}
2015-02-14 05:11:43 -08:00
2017-08-02 19:29:05 -07:00
# endif // SCHEDULER_H