Sync with last changes
This commit is contained in:
parent
e01dccc6b8
commit
c10a637853
|
@ -30,12 +30,29 @@ void initialiseFan();
|
|||
#define VVT_TIMER_COUNTER FTM1_CNT
|
||||
|
||||
#elif defined(CORE_STM32)
|
||||
#define ENABLE_VVT_TIMER()
|
||||
#define DISABLE_VVT_TIMER()
|
||||
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
|
||||
#define ENABLE_BOOST_TIMER() (TIM1)->CCER |= TIM_CCER_CC2E
|
||||
#define DISABLE_BOOST_TIMER() (TIM1)->CCER &= ~TIM_CCER_CC2E
|
||||
|
||||
#define ENABLE_BOOST_TIMER()
|
||||
#define DISABLE_BOOST_TIMER()
|
||||
#define ENABLE_VVT_TIMER() (TIM1)->CCER |= TIM_CCER_CC3E
|
||||
#define DISABLE_VVT_TIMER() (TIM1)->CCER &= ~TIM_CCER_CC3E
|
||||
|
||||
#define BOOST_TIMER_COMPARE (TIM1)->CCR2
|
||||
#define BOOST_TIMER_COUNTER (TIM1)->CNT
|
||||
#define VVT_TIMER_COMPARE (TIM1)->CCR3
|
||||
#define VVT_TIMER_COUNTER (TIM1)->CNT
|
||||
#else //libmaple core aka STM32DUINO
|
||||
#define ENABLE_BOOST_TIMER() (TIMER1->regs).gen->CCER |= TIMER_CCER_CC2E
|
||||
#define DISABLE_BOOST_TIMER() (TIMER1->regs).gen->CCER &= ~TIMER_CCER_CC2E
|
||||
|
||||
#define ENABLE_VVT_TIMER() (TIMER1->regs).gen->CCER |= TIMER_CCER_CC3E
|
||||
#define DISABLE_VVT_TIMER() (TIMER1->regs).gen->CCER &= ~TIMER_CCER_CC3E
|
||||
|
||||
#define BOOST_TIMER_COMPARE (TIMER1->regs).gen->CCR2
|
||||
#define BOOST_TIMER_COUNTER (TIMER1->regs).gen->CNT
|
||||
#define VVT_TIMER_COMPARE (TIMER1->regs).gen->CCR3
|
||||
#define VVT_TIMER_COUNTER (TIMER1->regs).gen->CNT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BOOST_PIN_LOW() *boost_pin_port &= ~(boost_pin_mask)
|
||||
|
@ -64,6 +81,10 @@ volatile bool vvt_pwm_state;
|
|||
unsigned int vvt_pwm_max_count; //Used for variable PWM frequency
|
||||
volatile unsigned int vvt_pwm_cur_value;
|
||||
long vvt_pwm_target_value;
|
||||
#if defined (CORE_TEENSY) || defined(CORE_STM32)
|
||||
static inline void boostInterrupt();
|
||||
static inline void vvtInterrupt();
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,7 +30,6 @@ void fanControl()
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CORE_AVR) || defined(CORE_TEENSY)
|
||||
void initialiseAuxPWM()
|
||||
{
|
||||
#if defined(CORE_AVR)
|
||||
|
@ -41,6 +40,10 @@ void initialiseAuxPWM()
|
|||
TCCR1B = (1 << CS12); //Timer1 Control Reg B: Timer Prescaler set to 256. 1 tick = 16uS. Refer to http://www.instructables.com/files/orig/F3T/TIKL/H3WSA4V7/F3TTIKLH3WSA4V7.jpg
|
||||
#elif defined(CORE_TEENSY)
|
||||
//REALLY NEED TO DO THIS!
|
||||
#elif defined(CORE_STM32)
|
||||
Timer1.attachInterrupt(2, boostInterrupt);
|
||||
Timer1.attachInterrupt(3, vvtInterrupt);
|
||||
Timer1.resume();
|
||||
#endif
|
||||
|
||||
boost_pin_port = portOutputRegister(digitalPinToPort(pinBoost));
|
||||
|
@ -48,8 +51,13 @@ void initialiseAuxPWM()
|
|||
vvt_pin_port = portOutputRegister(digitalPinToPort(pinVVT_1));
|
||||
vvt_pin_mask = digitalPinToBitMask(pinVVT_1);
|
||||
|
||||
boost_pwm_max_count = 1000000L / (16 * configPage3.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow freqneucies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (16 * configPage3.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle
|
||||
#if defined(CORE_STM32) //2uS resolution Min 8Hz, Max 5KHz
|
||||
boost_pwm_max_count = 1000000L / (configPage3.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow freqneucies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (configPage3.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle
|
||||
#else
|
||||
boost_pwm_max_count = 1000000L / (16 * configPage3.boostFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. The x2 is there because the frequency is stored at half value (in a byte) to allow freqneucies up to 511Hz
|
||||
vvt_pwm_max_count = 1000000L / (16 * configPage3.vvtFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle
|
||||
#endif
|
||||
//TIMSK1 |= (1 << OCIE1A); <---- Not required as compare A is turned on when needed by boost control
|
||||
ENABLE_VVT_TIMER(); //Turn on the B compare unit (ie turn on the interrupt)
|
||||
|
||||
|
@ -139,7 +147,7 @@ void vvtControl()
|
|||
//The interrupt to control the Boost PWM
|
||||
#if defined(CORE_AVR)
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
#elif defined (CORE_TEENSY)
|
||||
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
|
||||
static inline void boostInterrupt() //Most ARM chips can simply call a function
|
||||
#endif
|
||||
{
|
||||
|
@ -161,7 +169,7 @@ void vvtControl()
|
|||
//The interrupt to control the VVT PWM
|
||||
#if defined(CORE_AVR)
|
||||
ISR(TIMER1_COMPB_vect)
|
||||
#elif defined (CORE_TEENSY)
|
||||
#elif defined (CORE_TEENSY) || defined(CORE_STM32)
|
||||
static inline void vvtInterrupt() //Most ARM chips can simply call a function
|
||||
#endif
|
||||
{
|
||||
|
@ -180,10 +188,3 @@ void vvtControl()
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined(CORE_STM32)
|
||||
//YET TO BE IMPLEMENTED ON STM32
|
||||
void initialiseAuxPWM() { }
|
||||
void boostControl() { }
|
||||
void vvtControl() { }
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,7 +15,11 @@ uint8_t Glow, Ghigh;
|
|||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
HardwareSerial &CANSerial = Serial3;
|
||||
#elif defined(CORE_STM32)
|
||||
HardwareSerial &CANSerial = Serial2;
|
||||
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
|
||||
SerialUART &CANSerial = Serial2;
|
||||
#else //libmaple core aka STM32DUINO
|
||||
HardwareSerial &CANSerial = Serial2;
|
||||
#endif
|
||||
#elif defined(CORE_TEENSY)
|
||||
HardwareSerial &CANSerial = Serial2;
|
||||
#endif
|
||||
|
|
|
@ -9,14 +9,25 @@
|
|||
#define CORE_AVR
|
||||
#elif defined(CORE_TEENSY)
|
||||
#define BOARD_NR_GPIO_PINS 34
|
||||
#elif defined(STM32_MCU_SERIES) || defined(_VARIANT_ARDUINO_STM32_)
|
||||
#elif defined(STM32_MCU_SERIES) || defined(ARDUINO_ARCH_STM32) || defined(__STM32F1__) || defined(STM32F4) || defined(STM32)
|
||||
#define CORE_STM32
|
||||
#define LED_BUILTIN 33
|
||||
#if defined (STM32F1) || defined(__STM32F1__)
|
||||
#define BOARD_NR_GPIO_PINS 34
|
||||
#define LED_BUILTIN 33
|
||||
#elif defined(ARDUINO_BLACK_F407VE) || defined(STM32F4)
|
||||
#define BOARD_NR_GPIO_PINS 80
|
||||
#define LED_BUILTIN PA7
|
||||
#endif
|
||||
|
||||
extern "C" char* sbrk(int incr); //Used to freeRam
|
||||
inline unsigned char digitalPinToInterrupt(unsigned char Interrupt_pin) { return Interrupt_pin; } //This isn't included in the stm32duino libs (yet)
|
||||
#define portOutputRegister(port) (volatile byte *)( &(port->regs->ODR) ) //These are defined in STM32F1/variants/generic_stm32f103c/variant.h but return a non byte* value
|
||||
#define portInputRegister(port) (volatile byte *)( &(port->regs->IDR) ) //These are defined in STM32F1/variants/generic_stm32f103c/variant.h but return a non byte* value
|
||||
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
|
||||
#define portOutputRegister(port) (volatile byte *)( &(port->ODR) )
|
||||
#define portInputRegister(port) (volatile byte *)( &(port->IDR) )
|
||||
#else //libmaple core aka STM32DUINO
|
||||
#define portOutputRegister(port) (volatile byte *)( &(port->regs->ODR) ) //These are defined in STM32F1/variants/generic_stm32f103c/variant.h but return a non byte* value
|
||||
#define portInputRegister(port) (volatile byte *)( &(port->regs->IDR) ) //These are defined in STM32F1/variants/generic_stm32f103c/variant.h but return a non byte* value
|
||||
#endif
|
||||
#else
|
||||
#error Incorrect board selected. Please select the correct board (Usually Mega 2560) and upload again
|
||||
#endif
|
||||
|
@ -72,6 +83,12 @@
|
|||
#define BIT_SPARK2_UNUSED7 6
|
||||
#define BIT_SPARK2_UNUSED8 7
|
||||
|
||||
#define BIT_TIMER_1HZ 0
|
||||
#define BIT_TIMER_4HZ 1
|
||||
#define BIT_TIMER_10HZ 2
|
||||
#define BIT_TIMER_15HZ 3
|
||||
#define BIT_TIMER_30HZ 4
|
||||
|
||||
#define VALID_MAP_MAX 1022 //The largest ADC value that is valid for the MAP sensor
|
||||
#define VALID_MAP_MIN 2 //The smallest ADC value that is valid for the MAP sensor
|
||||
|
||||
|
|
|
@ -40,14 +40,19 @@ struct StepperIdle
|
|||
#define IDLE_TIMER_DISABLE() FTM2_C0SC &= ~FTM_CSC_CHIE
|
||||
|
||||
#elif defined(CORE_STM32)
|
||||
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
|
||||
#define IDLE_COUNTER (TIM1)->CNT
|
||||
#define IDLE_COMPARE (TIM1)->CCR4
|
||||
|
||||
//Placeholders only
|
||||
#define IDLE_COUNTER 0
|
||||
#define IDLE_COMPARE 0
|
||||
|
||||
#define IDLE_TIMER_ENABLE()
|
||||
#define IDLE_TIMER_DISABLE()
|
||||
#define IDLE_TIMER_ENABLE() (TIM1)->CCER |= TIM_CCER_CC4E
|
||||
#define IDLE_TIMER_DISABLE() (TIM1)->CCER &= ~TIM_CCER_CC4E
|
||||
#else //libmaple core aka STM32DUINO
|
||||
#define IDLE_COUNTER (TIMER1->regs).gen->CNT
|
||||
#define IDLE_COMPARE (TIMER1->regs).gen->CCR4
|
||||
|
||||
#define IDLE_TIMER_ENABLE() (TIMER1->regs).gen->CCER |= TIMER_CCER_CC4E
|
||||
#define IDLE_TIMER_DISABLE() (TIMER1->regs).gen->CCER &= ~TIMER_CCER_CC4E
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct table2D iacClosedLoopTable;
|
||||
|
@ -81,5 +86,8 @@ static inline void enableIdle();
|
|||
static inline byte isStepperHomed();
|
||||
static inline byte checkForStepping();
|
||||
static inline void doStep();
|
||||
#if defined (CORE_TEENSY) || defined(CORE_STM32)
|
||||
static inline void idleInterrupt();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -78,8 +78,9 @@ void initialiseIdle()
|
|||
NVIC_ENABLE_IRQ(IRQ_FTM2);
|
||||
}
|
||||
|
||||
#elif defined(MCU_STM32F103RB)
|
||||
|
||||
#elif defined(CORE_STM32)
|
||||
Timer1.attachInterrupt(4, idleInterrupt);
|
||||
Timer1.resume();
|
||||
#endif
|
||||
|
||||
//Initialising comprises of setting the 2D tables with the relevant values from the config pages
|
||||
|
@ -114,7 +115,11 @@ void initialiseIdle()
|
|||
idle_pin_mask = digitalPinToBitMask(pinIdle1);
|
||||
idle2_pin_port = portOutputRegister(digitalPinToPort(pinIdle2));
|
||||
idle2_pin_mask = digitalPinToBitMask(pinIdle2);
|
||||
idle_pwm_max_count = 1000000L / (16 * configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
|
||||
#if defined(CORE_STM32)
|
||||
idle_pwm_max_count = 1000000L / (configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 5KHz
|
||||
#else
|
||||
idle_pwm_max_count = 1000000L / (16 * configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
|
||||
#endif
|
||||
enableIdle();
|
||||
break;
|
||||
|
||||
|
@ -134,7 +139,11 @@ void initialiseIdle()
|
|||
idle_pin_mask = digitalPinToBitMask(pinIdle1);
|
||||
idle2_pin_port = portOutputRegister(digitalPinToPort(pinIdle2));
|
||||
idle2_pin_mask = digitalPinToBitMask(pinIdle2);
|
||||
idle_pwm_max_count = 1000000L / (16 * configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
|
||||
#if defined(CORE_STM32)
|
||||
idle_pwm_max_count = 1000000L / (configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 2uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 5KHz
|
||||
#else
|
||||
idle_pwm_max_count = 1000000L / (16 * configPage3.idleFreq * 2); //Converts the frequency in Hz to the number of ticks (at 16uS) it takes to complete 1 cycle. Note that the frequency is divided by 2 coming from TS to allow for up to 512hz
|
||||
#endif
|
||||
idlePID.SetOutputLimits(percentage(configPage1.iacCLminDuty, idle_pwm_max_count), percentage(configPage1.iacCLmaxDuty, idle_pwm_max_count));
|
||||
idlePID.SetTunings(configPage3.idleKP, configPage3.idleKI, configPage3.idleKD);
|
||||
idlePID.SetMode(AUTOMATIC); //Turn PID on
|
||||
|
@ -407,7 +416,6 @@ ISR(TIMER4_COMPC_vect)
|
|||
#elif defined (CORE_TEENSY) || defined (CORE_STM32)
|
||||
static inline void idleInterrupt() //Most ARM chips can simply call a function
|
||||
#endif
|
||||
#if defined(CORE_AVR) || defined (CORE_TEENSY)
|
||||
{
|
||||
if (idle_pwm_state)
|
||||
{
|
||||
|
@ -446,8 +454,3 @@ static inline void idleInterrupt() //Most ARM chips can simply call a function
|
|||
}
|
||||
|
||||
}
|
||||
#elif defined (CORE_STM32)
|
||||
{
|
||||
//No PWM idle for STM32 yet
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -162,59 +162,103 @@ See page 136 of the processors datasheet: http://www.atmel.com/Images/doc2549.pd
|
|||
#define uS_TO_TIMER_COMPARE_SLOW(uS) ((uS * 15) >> 5)
|
||||
|
||||
#elif defined(CORE_STM32)
|
||||
//Placeholders ONLY!
|
||||
|
||||
//https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/master/STM32F4/cores/maple/libmaple/timer.h#L51
|
||||
#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)
|
||||
#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.
|
||||
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
|
||||
#include "HardwareTimer.h"
|
||||
#define FUEL1_COUNTER (TIM2)->CNT
|
||||
#define FUEL2_COUNTER (TIM2)->CNT
|
||||
#define FUEL3_COUNTER (TIM2)->CNT
|
||||
#define FUEL4_COUNTER (TIM2)->CNT
|
||||
#define FUEL5_COUNTER (TIM2)->CNT
|
||||
|
||||
#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
|
||||
#define FUEL5_COUNTER (TIMER1->regs).gen->CNT
|
||||
#define IGN1_COUNTER (TIM3)->CNT
|
||||
#define IGN2_COUNTER (TIM3)->CNT
|
||||
#define IGN3_COUNTER (TIM3)->CNT
|
||||
#define IGN4_COUNTER (TIM3)->CNT
|
||||
#define IGN5_COUNTER (TIM3)->CNT
|
||||
|
||||
#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
|
||||
#define IGN5_COUNTER (TIMER1->regs).gen->CNT
|
||||
#define FUEL1_COMPARE (TIM2)->CCR1
|
||||
#define FUEL2_COMPARE (TIM2)->CCR2
|
||||
#define FUEL3_COMPARE (TIM2)->CCR3
|
||||
#define FUEL4_COMPARE (TIM2)->CCR4
|
||||
|
||||
#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
|
||||
#define IGN1_COMPARE (TIM3)->CCR1
|
||||
#define IGN2_COMPARE (TIM3)->CCR2
|
||||
#define IGN3_COMPARE (TIM3)->CCR3
|
||||
#define IGN4_COMPARE (TIM3)->CCR4
|
||||
#define IGN5_COMPARE (TIM3)->CCR1
|
||||
|
||||
#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
|
||||
#define IGN5_COMPARE (TIMER1->regs).gen->CCR1
|
||||
//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
|
||||
|
||||
//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
|
||||
#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 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
|
||||
#define IGN5_TIMER_ENABLE() (TIMER1->regs).gen->CCER |= TIMER_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 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
|
||||
#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
|
||||
#else //libmaple core aka STM32DUINO
|
||||
#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
|
||||
#define FUEL5_COUNTER (TIMER1->regs).gen->CNT
|
||||
|
||||
#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
|
||||
#define IGN5_TIMER_DISABLE() (TIMER1->regs).gen->CCER &= ~TIMER_CCER_CC1E
|
||||
#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
|
||||
#define IGN5_COUNTER (TIMER1->regs).gen->CNT
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
#define IGN5_COMPARE (TIMER1->regs).gen->CCR1
|
||||
|
||||
//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
|
||||
|
||||
#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
|
||||
#define IGN5_TIMER_ENABLE() (TIMER1->regs).gen->CCER |= TIMER_CCER_CC1E
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
#define IGN5_TIMER_DISABLE() (TIMER1->regs).gen->CCER &= ~TIMER_CCER_CC1E
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void initialiseSchedulers();
|
||||
|
|
|
@ -161,23 +161,40 @@ void initialiseSchedulers()
|
|||
NVIC_ENABLE_IRQ(IRQ_FTM1);
|
||||
|
||||
#elif defined(CORE_STM32)
|
||||
//see https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
|
||||
(TIMER1->regs).bas->PSC = (CYCLES_PER_MICROSECOND << 1) - 1; //2us resolution
|
||||
(TIMER2->regs).bas->PSC = (CYCLES_PER_MICROSECOND << 1) - 1; //2us resolution
|
||||
(TIMER3->regs).bas->PSC = (CYCLES_PER_MICROSECOND << 1) - 1; //2us resolution
|
||||
// Alternative 2us resolution:
|
||||
//TimerX.setPrescaleFactor(CYCLES_PER_MICROSECOND * 2U);
|
||||
#if defined(ARDUINO_ARCH_STM32) // STM32GENERIC core
|
||||
//see https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
|
||||
Timer1.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
|
||||
Timer2.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
|
||||
Timer3.setPrescaleFactor((HAL_RCC_GetHCLKFreq() * 2U)-1); //2us resolution
|
||||
Timer2.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
Timer2.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(TIMER_CH3, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(TIMER_CH4, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(2, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(3, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(4, TIMER_OUTPUT_COMPARE);
|
||||
Timer1.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
Timer3.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(TIMER_CH3, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(TIMER_CH4, TIMER_OUTPUT_COMPARE);
|
||||
#else //libmaple core aka STM32DUINO
|
||||
//see https://github.com/rogerclarkmelbourne/Arduino_STM32/blob/754bc2969921f1ef262bd69e7faca80b19db7524/STM32F1/system/libmaple/include/libmaple/timer.h#L444
|
||||
//(CYCLES_PER_MICROSECOND == 72, APB2 at 72MHz, APB1 at 36MHz).
|
||||
//Timer2 to 4 is on APB1, Timer1 on APB2. http://www.st.com/resource/en/datasheet/stm32f103cb.pdf sheet 12
|
||||
Timer1.setPrescaleFactor((72 * 2U)-1); //2us resolution
|
||||
Timer2.setPrescaleFactor((36 * 2U)-1); //2us resolution
|
||||
Timer3.setPrescaleFactor((36 * 2U)-1); //2us resolution
|
||||
Timer2.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(TIMER_CH3, TIMER_OUTPUT_COMPARE);
|
||||
Timer2.setMode(TIMER_CH4, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
Timer3.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(TIMER_CH2, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(TIMER_CH3, TIMER_OUTPUT_COMPARE);
|
||||
Timer3.setMode(TIMER_CH4, TIMER_OUTPUT_COMPARE);
|
||||
|
||||
#endif
|
||||
Timer2.attachInterrupt(1, fuelSchedule1Interrupt);
|
||||
Timer2.attachInterrupt(2, fuelSchedule2Interrupt);
|
||||
Timer2.attachInterrupt(3, fuelSchedule3Interrupt);
|
||||
|
@ -187,7 +204,11 @@ void initialiseSchedulers()
|
|||
Timer3.attachInterrupt(2, ignitionSchedule2Interrupt);
|
||||
Timer3.attachInterrupt(3, ignitionSchedule3Interrupt);
|
||||
Timer3.attachInterrupt(4, ignitionSchedule4Interrupt);
|
||||
Timer1.attachInterrupt(1, ignitionSchedule5Interrupt);
|
||||
|
||||
Timer1.resume();
|
||||
Timer2.resume();
|
||||
Timer3.resume();
|
||||
#endif
|
||||
|
||||
fuelSchedule1.Status = OFF;
|
||||
|
|
|
@ -144,20 +144,23 @@ void setup()
|
|||
table3D_setSize(&trim3Table, 6);
|
||||
table3D_setSize(&trim4Table, 6);
|
||||
|
||||
#if defined(CORE_STM32)
|
||||
EEPROM.init();
|
||||
#endif
|
||||
loadConfig();
|
||||
doUpdates(); //Check if any data items need updating (Occurs ith firmware updates)
|
||||
|
||||
Serial.begin(115200);
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) //ATmega2561 does not have Serial3
|
||||
if (configPage10.enable_canbus == 1) { Serial3.begin(115200); }
|
||||
if (configPage10.enable_canbus == 1) { CANSerial.begin(115200); }
|
||||
#elif defined(CORE_STM32)
|
||||
if (configPage10.enable_canbus == 1) { Serial2.begin(115200); }
|
||||
if (configPage10.enable_canbus == 1) { CANSerial.begin(115200); }
|
||||
else if (configPage10.enable_canbus == 2)
|
||||
{
|
||||
//enable local can interface
|
||||
}
|
||||
#elif defined(CORE_TEENSY)
|
||||
if (configPage10.enable_canbus == 1) { Serial2.begin(115200); }
|
||||
if (configPage10.enable_canbus == 1) { CANSerial.begin(115200); }
|
||||
else if (configPage10.enable_canbus == 2)
|
||||
{
|
||||
//Teensy onboard CAN not used currently
|
||||
|
@ -635,10 +638,11 @@ void setup()
|
|||
void loop()
|
||||
{
|
||||
mainLoopCount++;
|
||||
LOOP_TIMER = TIMER_mask;
|
||||
//Check for any requets from serial. Serial operations are checked under 2 scenarios:
|
||||
// 1) Every 64 loops (64 Is more than fast enough for TunerStudio). This function is equivalent to ((loopCount % 64) == 1) but is considerably faster due to not using the mod or division operations
|
||||
// 2) If the amount of data in the serial buffer is greater than a set threhold (See globals.h). This is to avoid serial buffer overflow when large amounts of data is being sent
|
||||
if ( ((mainLoopCount & 31) == 1) or (Serial.available() > SERIAL_BUFFER_THRESHOLD) )
|
||||
if ( (BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ)) or (Serial.available() > SERIAL_BUFFER_THRESHOLD) )
|
||||
{
|
||||
if (Serial.available() > 0)
|
||||
{
|
||||
|
@ -650,7 +654,7 @@ void loop()
|
|||
//if serial3 interface is enabled then check for serial3 requests.
|
||||
if (configPage10.enable_canbus == 1)
|
||||
{
|
||||
if ( ((mainLoopCount & 31) == 1) or (CANSerial.available() > SERIAL_BUFFER_THRESHOLD) )
|
||||
if ( (BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ)) or (CANSerial.available() > SERIAL_BUFFER_THRESHOLD) )
|
||||
{
|
||||
if (CANSerial.available() > 0)
|
||||
{
|
||||
|
@ -659,13 +663,13 @@ void loop()
|
|||
}
|
||||
}
|
||||
|
||||
#elif defined(CORE_STM32)
|
||||
#elif defined(CORE_TEENSY) || defined(CORE_STM32)
|
||||
//if can or secondary serial interface is enabled then check for requests.
|
||||
if (configPage10.enable_canbus == 1) //secondary serial interface enabled
|
||||
{
|
||||
if ( ((mainLoopCount & 31) == 1) or (Serial2.available() > SERIAL_BUFFER_THRESHOLD) )
|
||||
if ( (BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ)) or (CANSerial.available() > SERIAL_BUFFER_THRESHOLD) )
|
||||
{
|
||||
if (Serial2.available() > 0)
|
||||
if (CANSerial.available() > 0)
|
||||
{
|
||||
canCommand();
|
||||
}
|
||||
|
@ -674,23 +678,7 @@ void loop()
|
|||
else if (configPage10.enable_canbus == 2) // can module enabled
|
||||
{
|
||||
//check local can module
|
||||
}
|
||||
#elif defined(CORE_TEENSY)
|
||||
//if can or secondary serial interface is enabled then check for requests.
|
||||
if (configPage10.enable_canbus == 1) //secondary serial interface enabled
|
||||
{
|
||||
if ( ((mainLoopCount & 31) == 1) or (Serial2.available() > SERIAL_BUFFER_THRESHOLD) )
|
||||
{
|
||||
if (Serial2.available() > 0)
|
||||
{
|
||||
canCommand();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (configPage10.enable_canbus == 2) // can module enabled
|
||||
{
|
||||
//check local can module
|
||||
// if ( ((mainLoopCount & 31) == 1) or (CANbus0.available())
|
||||
// if ( (BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ)) or (CANbus0.available())
|
||||
// {
|
||||
// CANbus0.read(rx_msg);
|
||||
// }
|
||||
|
@ -755,8 +743,9 @@ void loop()
|
|||
//-----------------------------------------------------------------------------------------------------
|
||||
readMAP();
|
||||
|
||||
if ((mainLoopCount & 31) == 1) //Every 32 loops
|
||||
if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_15HZ)) //Every 32 loops
|
||||
{
|
||||
BIT_CLEAR(TIMER_mask, BIT_TIMER_15HZ);
|
||||
readTPS(); //TPS reading to be performed every 32 loops (any faster and it can upset the TPSdot sampling time)
|
||||
|
||||
//Check for launching/flat shift (clutch) can be done around here too
|
||||
|
@ -803,13 +792,15 @@ void loop()
|
|||
//Most boost tends to run at about 30Hz, so placing it here ensures a new target time is fetched frequently enough
|
||||
boostControl();
|
||||
}
|
||||
if( (mainLoopCount & 63) == 1) //Every 64 loops
|
||||
if(BIT_CHECK(LOOP_TIMER, BIT_TIMER_30HZ)) //Every 64 loops
|
||||
{
|
||||
//Nothing here currently
|
||||
BIT_CLEAR(TIMER_mask, BIT_TIMER_30HZ);
|
||||
}
|
||||
//The IAT and CLT readings can be done less frequently. This still runs about 4 times per second
|
||||
if ((mainLoopCount & 255) == 1) //Every 256 loops
|
||||
if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_4HZ)) //Every 256 loops
|
||||
{
|
||||
BIT_CLEAR(TIMER_mask, BIT_TIMER_4HZ);
|
||||
readCLT();
|
||||
readIAT();
|
||||
readO2();
|
||||
|
@ -869,9 +860,10 @@ void loop()
|
|||
vvtControl();
|
||||
idleControl(); //Perform any idle related actions. Even at higher frequencies, running 4x per second is sufficient.
|
||||
}
|
||||
if ((mainLoopCount & 1023) == 1) //Every 1024 loops (Approx. 1 per second)
|
||||
if (BIT_CHECK(LOOP_TIMER, BIT_TIMER_1HZ)) //Every 1024 loops (Approx. 1 per second)
|
||||
{
|
||||
//Approx. once per second
|
||||
BIT_CLEAR(TIMER_mask, BIT_TIMER_1HZ);
|
||||
readBaro();
|
||||
}
|
||||
|
||||
|
|
|
@ -409,82 +409,103 @@ int get3DTableValue(struct table3D *fromTable, int Y_in, int X_in)
|
|||
return tableResult;
|
||||
}
|
||||
/* Executed a benchmark on all options and this is the results
|
||||
* Stadard:226224 91 |FP Math:32240 91.89 |Clean code:34056 91, Number of loops:2500
|
||||
*
|
||||
* @Mega: Stadard:464276 92 |FP Math:893104 92.57 |Clean code:641280 92 , Number of loops:5000
|
||||
* @STM32F1: Stadard:21449 92 |FP Math:125707 92.57 |Clean code:11634 92 , Number of loops:5000
|
||||
* @STM32F4: Stadard:7275 92 |FP Math:5724 92.57 |Clean code:4742 92 , Number of loops:5000
|
||||
|
||||
//This function pulls a value from a 3D table given a target for X and Y coordinates.
|
||||
//It performs a 2D linear interpolation as descibred in: http://www.megamanual.com/v22manual/ve_tuner.pdf
|
||||
float get3DTableValueF(struct table3D *fromTable, int Y, int X)
|
||||
{
|
||||
float m, n, o ,p, q, r;
|
||||
byte xMin, xMax;
|
||||
byte yMin, yMax;
|
||||
int yMaxValue, yMinValue;
|
||||
int xMaxValue, xMinValue;
|
||||
float tableResult = 0;
|
||||
|
||||
if(fromTable->lastXMin==0) {fromTable->lastXMin = fromTable->xSize-1;}
|
||||
else {xMin = fromTable->lastXMin;}
|
||||
if(fromTable->lastYMin==0) {fromTable->lastYMin = fromTable->ySize-1;}
|
||||
else {yMin = fromTable->lastYMin;}
|
||||
//yMin = fromTable->lastYMin;
|
||||
|
||||
if(xMin>fromTable->xSize-1)
|
||||
{
|
||||
fromTable->lastXMin = fromTable->xSize-1;
|
||||
xMin = fromTable->xSize-1;
|
||||
}
|
||||
if(yMin>fromTable->ySize-1)
|
||||
{
|
||||
fromTable->lastYMin = fromTable->ySize-1;
|
||||
yMin = fromTable->ySize-1;
|
||||
}
|
||||
xMin = fromTable->lastXMin;
|
||||
yMin = fromTable->lastYMin;
|
||||
if(xMin == 0) { xMin = fromTable->xSize-1; }
|
||||
if(yMin == 0) { yMin = fromTable->ySize-1; }
|
||||
|
||||
do //RPM axis
|
||||
{
|
||||
if(X>=fromTable->axisX[xMin]) {break;}
|
||||
if(X == fromTable->axisX[xMin])
|
||||
{
|
||||
xMax = xMin;
|
||||
break;
|
||||
}
|
||||
else if(X > fromTable->axisX[xMin])
|
||||
{
|
||||
if (xMin == fromTable->xSize-1) { xMax = xMin; } //Overflow protection
|
||||
else { xMax = xMin + 1; }
|
||||
break;
|
||||
}
|
||||
xMin--;
|
||||
}while(1);
|
||||
fromTable->lastXMin = xMin + 1;
|
||||
}while(true);
|
||||
|
||||
do //MAP axis
|
||||
{
|
||||
if(Y<=fromTable->axisY[yMin]) {break;}
|
||||
if(Y == fromTable->axisY[yMin])
|
||||
{
|
||||
yMax = yMin;
|
||||
break;
|
||||
}
|
||||
else if(Y < fromTable->axisY[yMin])
|
||||
{
|
||||
if (yMin == fromTable->ySize-1) { yMax = yMin; } //Overflow protection
|
||||
else { yMax = yMin + 1; }
|
||||
break;
|
||||
}
|
||||
yMin--;
|
||||
}while(1);
|
||||
fromTable->lastYMin = yMin + 1;
|
||||
}while(true);
|
||||
|
||||
xMax = xMin + 1;
|
||||
yMax = yMin + 1;
|
||||
if (xMax>fromTable->xSize-1) //Overflow protection
|
||||
{
|
||||
xMax = fromTable->xSize-1;
|
||||
xMin = xMax - 1;
|
||||
}
|
||||
if (yMax>fromTable->ySize-1) //Overflow protection
|
||||
{
|
||||
yMax = fromTable->ySize-1;
|
||||
yMin = yMax - 1;
|
||||
}
|
||||
|
||||
yMaxValue = fromTable->axisY[yMax];
|
||||
yMinValue = fromTable->axisY[yMin];
|
||||
xMaxValue = fromTable->axisX[xMax];
|
||||
xMinValue = fromTable->axisX[xMin];
|
||||
fromTable->lastXMin = xMax;
|
||||
fromTable->lastYMin = yMax;
|
||||
|
||||
int A = fromTable->values[yMin][xMin];
|
||||
int B = fromTable->values[yMin][xMax];
|
||||
int C = fromTable->values[yMax][xMin];
|
||||
int D = fromTable->values[yMax][xMax];
|
||||
if( (A == B) && (A == C) && (A == D) ) { tableResult = A; }
|
||||
else if(xMin == xMax) // Same RPM axys do a simple 2D (27% faster on Mega on worst case, up to 500%)
|
||||
{
|
||||
int yMaxValue = fromTable->axisY[yMax];
|
||||
int yMinValue = fromTable->axisY[yMin];
|
||||
float q;
|
||||
q = ((float)(Y - yMinValue) * (C - A)) / (yMaxValue - yMinValue);
|
||||
tableResult = A + q;
|
||||
}
|
||||
else if(yMin == yMax) // Same MAP axys do a simple 2D (27% faster on Mega on worst case, up to 500%)
|
||||
{
|
||||
int xMaxValue = fromTable->axisX[xMax];
|
||||
int xMinValue = fromTable->axisX[xMin];
|
||||
float q;
|
||||
q = ((float)(X - xMinValue) * (B - A)) / (xMaxValue - xMinValue);
|
||||
tableResult = A + q;
|
||||
}
|
||||
else
|
||||
{
|
||||
int yMaxValue = fromTable->axisY[yMax];
|
||||
int yMinValue = fromTable->axisY[yMin];
|
||||
int xMaxValue = fromTable->axisX[xMax];
|
||||
int xMinValue = fromTable->axisX[xMin];
|
||||
|
||||
float m, n, o , p, q, r;
|
||||
if (xMaxValue == xMinValue) { p = (float)X - xMinValue; }
|
||||
else { p = ((float)X - xMinValue) / (xMaxValue - xMinValue); }
|
||||
if (yMaxValue == yMinValue) { q = (float)Y - yMinValue; }
|
||||
else { q = ((float)Y - yMinValue) / (yMaxValue - yMinValue); }
|
||||
|
||||
p = float(X - xMinValue) / (xMaxValue - xMinValue); //(RPM - RPM[1])/(RPM[2]- RPM[1])
|
||||
q = float(Y - yMinValue) / (yMaxValue - yMinValue); //(MAP - MAP[1])/(MAP[2]- MAP[1])
|
||||
|
||||
m = (1.0-p) * (1.0-q);
|
||||
n = p * (1-q);
|
||||
o = (1-p) * q;
|
||||
r = p * q;
|
||||
|
||||
return ( (A * m) + (B * n) + (C * o) + (D * r) );
|
||||
m = (1.0-p) * (1.0-q);
|
||||
n = p * (1-q);
|
||||
o = (1-p) * q;
|
||||
r = p * q;
|
||||
tableResult = ( (A * m) + (B * n) + (C * o) + (D * r) );
|
||||
}
|
||||
return tableResult;
|
||||
}
|
||||
*/
|
||||
|
||||
//This function pulls a value from a 3D table given a target for X and Y coordinates.
|
||||
//It performs a 2D linear interpolation as descibred in: http://www.megamanual.com/v22manual/ve_tuner.pdf
|
||||
int get3DTableValueS(struct table3D *fromTable, int Y, int X)
|
||||
{
|
||||
byte xMin, xMax;
|
||||
|
@ -498,68 +519,62 @@ int get3DTableValueS(struct table3D *fromTable, int Y, int X)
|
|||
|
||||
do //RPM axis
|
||||
{
|
||||
if(X > fromTable->axisX[xMin])
|
||||
{
|
||||
if (xMin == (fromTable->xSize-1) ) { xMax = xMin; } //Overflow protection
|
||||
else { xMax = xMin + 1; }
|
||||
break;
|
||||
}
|
||||
else if(X == fromTable->axisX[xMin])
|
||||
if(X == fromTable->axisX[xMin])
|
||||
{
|
||||
xMax = xMin;
|
||||
break;
|
||||
}
|
||||
else if(X > fromTable->axisX[xMin])
|
||||
{
|
||||
if (xMin == fromTable->xSize-1) { xMax = xMin; } //Overflow protection
|
||||
else { xMax = xMin + 1; }
|
||||
break;
|
||||
}
|
||||
xMin--;
|
||||
}while(true);
|
||||
|
||||
do //MAP axis
|
||||
{
|
||||
if(Y < fromTable->axisY[yMin])
|
||||
{
|
||||
if (yMin == (fromTable->ySize-1) ) { yMax = yMin; } //Overflow protection
|
||||
else { yMax = yMin + 1; }
|
||||
break;
|
||||
}
|
||||
else if(Y == fromTable->axisY[yMin])
|
||||
if(Y == fromTable->axisY[yMin])
|
||||
{
|
||||
yMax = yMin;
|
||||
break;
|
||||
}
|
||||
else if(Y < fromTable->axisY[yMin])
|
||||
{
|
||||
if (yMin == fromTable->ySize-1) { yMax = yMin; } //Overflow protection
|
||||
else { yMax = yMin + 1; }
|
||||
break;
|
||||
}
|
||||
yMin--;
|
||||
}while(true);
|
||||
|
||||
fromTable->lastXMin = xMax;
|
||||
fromTable->lastYMin = yMax;
|
||||
|
||||
//Serial.print("xMin, xMax ");Serial.print(xMin);Serial.print(",");Serial.println(xMax);
|
||||
//Serial.print("yMin, yMax ");Serial.print(yMin);Serial.print(",");Serial.println(yMax);
|
||||
|
||||
int A = fromTable->values[yMin][xMin];
|
||||
if((xMin == xMax) && (yMin == yMax)) { tableResult = A; }
|
||||
else if(xMin == xMax) // Simple 2D
|
||||
int B = fromTable->values[yMin][xMax];
|
||||
int C = fromTable->values[yMax][xMin];
|
||||
int D = fromTable->values[yMax][xMax];
|
||||
if( (A == B) && (A == C) && (A == D) ) { tableResult = A; }
|
||||
else if(xMin == xMax) // Same RPM axys do a simple 2D (27% faster on Mega on worst case, up to 500%)
|
||||
{
|
||||
int D = fromTable->values[yMax][xMax];
|
||||
int yMaxValue = fromTable->axisY[yMax];
|
||||
int yMinValue = fromTable->axisY[yMin];
|
||||
long q = (long)Y - yMinValue;
|
||||
q = ((q << 6) * (D - A)) / (yMaxValue - yMinValue);
|
||||
long q;
|
||||
q = (((long)(Y - yMinValue) << 6) * (C - A)) / (yMaxValue - yMinValue);
|
||||
tableResult = A + (q >> 6);
|
||||
}
|
||||
else if(yMin == yMax) // Simple 2D
|
||||
else if(yMin == yMax) // Same MAP axys do a simple 2D (27% faster on Mega on worst case, up to 500%)
|
||||
{
|
||||
int D = fromTable->values[yMax][xMax];
|
||||
int xMaxValue = fromTable->axisX[xMax];
|
||||
int xMinValue = fromTable->axisX[xMin];
|
||||
long q = (long)X - xMinValue;
|
||||
q = ((q << 6) * (D - A)) / (xMaxValue - xMinValue);
|
||||
long q;
|
||||
q = (((long)(X - xMinValue) << 6) * (B - A)) / (xMaxValue - xMinValue);
|
||||
tableResult = A + (q >> 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
int B = fromTable->values[yMin][xMax];
|
||||
int C = fromTable->values[yMax][xMin];
|
||||
int D = fromTable->values[yMax][xMax];
|
||||
|
||||
int yMaxValue = fromTable->axisY[yMax];
|
||||
int yMinValue = fromTable->axisY[yMin];
|
||||
int xMaxValue = fromTable->axisX[xMax];
|
||||
|
@ -575,6 +590,7 @@ int get3DTableValueS(struct table3D *fromTable, int Y, int X)
|
|||
q = (long)Y - yMinValue;
|
||||
q = (q << 8);
|
||||
}
|
||||
//Standard case
|
||||
else
|
||||
{
|
||||
q = long(Y) - yMaxValue;
|
||||
|
@ -586,6 +602,7 @@ int get3DTableValueS(struct table3D *fromTable, int Y, int X)
|
|||
int o = ((256-p) * q) >> 8;
|
||||
int r = (p * q) >> 8;
|
||||
tableResult = ( (A * m) + (B * n) + (C * o) + (D * r) ) >> 8;
|
||||
}
|
||||
}
|
||||
return tableResult;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -19,8 +19,10 @@ Hence we will preload the timer with 131 cycles to leave 125 until overflow (1ms
|
|||
#ifndef TIMERS_H
|
||||
#define TIMERS_H
|
||||
|
||||
volatile int loop100ms;
|
||||
volatile int loop250ms;
|
||||
volatile byte loop33ms;
|
||||
volatile byte loop66ms;
|
||||
volatile byte loop100ms;
|
||||
volatile byte loop250ms;
|
||||
volatile int loopSec;
|
||||
|
||||
volatile unsigned int dwellLimit_uS;
|
||||
|
|
|
@ -42,8 +42,9 @@ void initialiseTimers()
|
|||
#elif defined(CORE_STM32)
|
||||
Timer4.setPeriod(1000); // Set up period
|
||||
// Set up an interrupt
|
||||
Timer4.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.setMode(1, TIMER_OUTPUT_COMPARE);
|
||||
Timer4.attachInterrupt(1, oneMSInterval);
|
||||
Timer4.resume(); //Start Timer
|
||||
#endif
|
||||
|
||||
dwellLimit_uS = (1000 * configPage2.dwellLimit);
|
||||
|
@ -61,6 +62,8 @@ void oneMSInterval() //Most ARM chips can simply call a function
|
|||
{
|
||||
|
||||
//Increment Loop Counters
|
||||
loop33ms++;
|
||||
loop66ms++;
|
||||
loop100ms++;
|
||||
loop250ms++;
|
||||
loopSec++;
|
||||
|
@ -78,11 +81,29 @@ void oneMSInterval() //Most ARM chips can simply call a function
|
|||
if(ignitionSchedule4.Status == RUNNING) { if( (ignitionSchedule4.startTime < targetOverdwellTime) && (configPage2.useDwellLim) && (isCrankLocked != true) ) { endCoil4Charge(); } }
|
||||
if(ignitionSchedule5.Status == RUNNING) { if( (ignitionSchedule5.startTime < targetOverdwellTime) && (configPage2.useDwellLim) && (isCrankLocked != true) ) { endCoil5Charge(); } }
|
||||
|
||||
//15Hz loop
|
||||
if (loop66ms == 66)
|
||||
{
|
||||
loop66ms = 0;
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_15HZ);
|
||||
}
|
||||
|
||||
//30Hz loop
|
||||
if (loop33ms == 33)
|
||||
{
|
||||
loop33ms = 0;
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_30HZ);
|
||||
}
|
||||
|
||||
//Loop executed every 100ms loop
|
||||
//Anything inside this if statement will run every 100ms.
|
||||
if (loop100ms == 100)
|
||||
{
|
||||
loop100ms = 0; //Reset counter
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_10HZ);
|
||||
#if defined(CORE_STM32) //debug purpose, only visal for running code
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
#endif
|
||||
|
||||
currentStatus.rpmDOT = (currentStatus.RPM - lastRPM_100ms) * 10; //This is the RPM per second that the engine has accelerated/decelleratedin the last loop
|
||||
lastRPM_100ms = currentStatus.RPM; //Record the current RPM for next calc
|
||||
|
@ -93,6 +114,7 @@ void oneMSInterval() //Most ARM chips can simply call a function
|
|||
if (loop250ms == 250)
|
||||
{
|
||||
loop250ms = 0; //Reset Counter
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_4HZ);
|
||||
|
||||
#if defined(CORE_AVR)
|
||||
//Reset watchdog timer (Not active currently)
|
||||
|
@ -107,6 +129,7 @@ void oneMSInterval() //Most ARM chips can simply call a function
|
|||
if (loopSec == 1000)
|
||||
{
|
||||
loopSec = 0; //Reset counter.
|
||||
BIT_SET(TIMER_mask, BIT_TIMER_1HZ);
|
||||
|
||||
dwellLimit_uS = (1000 * configPage2.dwellLimit); //Update uS value incase setting has changed
|
||||
currentStatus.crankRPM = ((unsigned int)configPage2.crankRPM * 100);
|
||||
|
|
|
@ -12,4 +12,45 @@ unsigned int PW();
|
|||
unsigned int PW_SD();
|
||||
unsigned int PW_AN();
|
||||
|
||||
//This is dumb, but it'll do for now to get things compiling
|
||||
#if defined(CORE_STM32)
|
||||
//STM32F1/variants/.../board.cpp
|
||||
#if defined (STM32F4)
|
||||
#define A0 PA0
|
||||
#define A1 PA1
|
||||
#define A2 PA2
|
||||
#define A3 PA3
|
||||
#define A4 PA4
|
||||
#define A5 PA5
|
||||
#define A6 PA6
|
||||
#define A7 PA7
|
||||
#define A8 PB0
|
||||
#define A9 PB1
|
||||
#define A10 PC0
|
||||
#define A11 PC1
|
||||
#define A12 PC2
|
||||
#define A13 PC3
|
||||
#define A14 PC4
|
||||
#define A15 PC5
|
||||
#else
|
||||
#define A0 PB0
|
||||
#define A1 PA7
|
||||
#define A2 PA6
|
||||
#define A3 PA5
|
||||
#define A4 PA4
|
||||
#define A5 PA3
|
||||
#define A6 PA2
|
||||
#define A7 PA1
|
||||
#define A8 PA0
|
||||
//STM32F1 have only 9 12bit adc
|
||||
#define A9 PB0
|
||||
#define A10 PA7
|
||||
#define A11 PA6
|
||||
#define A12 PA5
|
||||
#define A13 PA4
|
||||
#define A14 PA3
|
||||
#define A15 PA2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // UTILS_H
|
||||
|
|
|
@ -42,28 +42,6 @@ uint16_t freeRam ()
|
|||
|
||||
void setPinMapping(byte boardID)
|
||||
{
|
||||
//This is dumb, but it'll do for now to get things compiling
|
||||
#if defined(CORE_STM32)
|
||||
//STM32F1/variants/.../board.cpp
|
||||
#define A0 boardADCPins[0]
|
||||
#define A1 boardADCPins[1]
|
||||
#define A2 boardADCPins[2]
|
||||
#define A3 boardADCPins[3]
|
||||
#define A4 boardADCPins[4]
|
||||
#define A5 boardADCPins[5]
|
||||
#define A6 boardADCPins[6]
|
||||
#define A7 boardADCPins[7]
|
||||
#define A8 boardADCPins[8]
|
||||
#define A9 boardADCPins[9]
|
||||
//STM32F1 have only 9 12bit adc
|
||||
#define A10 boardADCPins[0]
|
||||
#define A11 boardADCPins[1]
|
||||
#define A12 boardADCPins[2]
|
||||
#define A13 boardADCPins[3]
|
||||
#define A14 boardADCPins[4]
|
||||
#define A15 boardADCPins[5]
|
||||
#endif
|
||||
|
||||
switch (boardID)
|
||||
{
|
||||
case 0:
|
||||
|
@ -168,35 +146,6 @@ void setPinMapping(byte boardID)
|
|||
pinCoil4 = 21;
|
||||
pinCoil3 = 30;
|
||||
pinO2 = A22;
|
||||
#elif defined(CORE_STM32)
|
||||
//http://docs.leaflabs.com/static.leaflabs.com/pub/leaflabs/maple-docs/0.0.12/hardware/maple-mini.html#master-pin-map
|
||||
//pins 23, 24 and 33 couldn't be used
|
||||
pinInjector1 = 15; //Output pin injector 1 is on
|
||||
pinInjector2 = 16; //Output pin injector 2 is on
|
||||
pinInjector3 = 17; //Output pin injector 3 is on
|
||||
pinInjector4 = 18; //Output pin injector 4 is on
|
||||
pinCoil1 = 19; //Pin for coil 1
|
||||
pinCoil2 = 20; //Pin for coil 2
|
||||
pinCoil3 = 21; //Pin for coil 3
|
||||
pinCoil4 = 26; //Pin for coil 4
|
||||
pinCoil5 = 27; //Pin for coil 5
|
||||
pinTPS = A0; //TPS input pin
|
||||
pinMAP = A1; //MAP sensor pin
|
||||
pinIAT = A2; //IAT sensor pin
|
||||
pinCLT = A3; //CLS sensor pin
|
||||
pinO2 = A4; //O2 Sensor pin
|
||||
pinBat = A5; //Battery reference voltage pin
|
||||
pinStepperDir = 12; //Direction pin for DRV8825 driver
|
||||
pinStepperStep = 13; //Step pin for DRV8825 driver
|
||||
pinStepperEnable = 14; //Enable pin for DRV8825
|
||||
pinDisplayReset = 2; // OLED reset pin
|
||||
pinFan = 1; //Pin for the fan output
|
||||
pinFuelPump = 0; //Fuel pump output
|
||||
pinTachOut = 31; //Tacho output pin
|
||||
//external interrupt enabled pins
|
||||
pinFlex = 32; // Flex sensor (Must be external interrupt enabled)
|
||||
pinTrigger = 25; //The CAS pin
|
||||
pinTrigger2 = 22; //The Cam Sensor pin
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -245,6 +194,37 @@ void setPinMapping(byte boardID)
|
|||
pinCoil4 = 29;
|
||||
pinCoil3 = 30;
|
||||
pinO2 = A22;
|
||||
#elif defined(STM32F4)
|
||||
pinInjector1 = PE7; //Output pin injector 1 is on
|
||||
pinInjector2 = PE8; //Output pin injector 2 is on
|
||||
pinInjector3 = PE9; //Output pin injector 3 is on
|
||||
pinInjector4 = PE10; //Output pin injector 4 is on
|
||||
pinInjector5 = PE11; //Output pin injector 5 is on
|
||||
pinCoil1 = PB10; //Pin for coil 1
|
||||
pinCoil2 = PB11; //Pin for coil 2
|
||||
pinCoil3 = PB12; //Pin for coil 3
|
||||
pinCoil4 = PB13; //Pin for coil 4
|
||||
pinCoil5 = PB14; //Pin for coil 5
|
||||
pinTPS = A0; //TPS input pin
|
||||
pinMAP = A1; //MAP sensor pin
|
||||
pinIAT = A2; //IAT sensor pin
|
||||
pinCLT = A3; //CLS sensor pin
|
||||
pinO2 = A4; //O2 Sensor pin
|
||||
pinBat = A5; //Battery reference voltage pin
|
||||
pinBaro = A6;
|
||||
pinStepperDir = PD8; //Direction pin for DRV8825 driver
|
||||
pinStepperStep = PB15; //Step pin for DRV8825 driver
|
||||
pinStepperEnable = PD9; //Enable pin for DRV8825
|
||||
pinDisplayReset = PE1; // OLED reset pin
|
||||
pinFan = PE2; //Pin for the fan output
|
||||
pinFuelPump = PA6; //Fuel pump output
|
||||
pinTachOut = PA7; //Tacho output pin
|
||||
//external interrupt enabled pins
|
||||
pinFlex = PC4; // Flex sensor (Must be external interrupt enabled)
|
||||
pinTrigger = PC5; //The CAS pin
|
||||
pinTrigger2 = PC6; //The Cam Sensor pin
|
||||
pinBoost = PE0; //Boost control
|
||||
pinVVT_1 = PE1; //Default VVT output
|
||||
#elif defined(CORE_STM32)
|
||||
//http://docs.leaflabs.com/static.leaflabs.com/pub/leaflabs/maple-docs/0.0.12/hardware/maple-mini.html#master-pin-map
|
||||
//pins 23, 24 and 33 couldn't be used
|
||||
|
@ -274,6 +254,9 @@ void setPinMapping(byte boardID)
|
|||
pinFlex = 32; // Flex sensor (Must be external interrupt enabled)
|
||||
pinTrigger = 25; //The CAS pin
|
||||
pinTrigger2 = 22; //The Cam Sensor pin
|
||||
pinBaro = pinMAP;
|
||||
pinBoost = 1; //Boost control
|
||||
pinVVT_1 = 0; //Default VVT output
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -456,7 +439,7 @@ void setPinMapping(byte boardID)
|
|||
if ( (configPage4.fanPin != 0) && (configPage4.fanPin < BOARD_NR_GPIO_PINS) ) { pinFan = configPage4.fanPin; }
|
||||
if ( (configPage3.boostPin != 0) && (configPage3.boostPin < BOARD_NR_GPIO_PINS) ) { pinBoost = configPage3.boostPin; }
|
||||
if ( (configPage3.vvtPin != 0) && (configPage3.vvtPin < BOARD_NR_GPIO_PINS) ) { pinVVT_1 = configPage3.vvtPin; }
|
||||
if ( (configPage3.useExtBaro != 0) ) { pinBaro = configPage3.baroPin + A0; }
|
||||
if ( (configPage3.useExtBaro != 0) && (configPage3.baroPin < BOARD_NR_GPIO_PINS) ) { pinBaro = configPage3.baroPin + A0; }
|
||||
|
||||
//Finally, set the relevant pin modes for outputs
|
||||
pinMode(pinCoil1, OUTPUT);
|
||||
|
@ -508,25 +491,28 @@ void setPinMapping(byte boardID)
|
|||
pump_pin_port = portOutputRegister(digitalPinToPort(pinFuelPump));
|
||||
pump_pin_mask = digitalPinToBitMask(pinFuelPump);
|
||||
|
||||
//And for inputs
|
||||
//And for inputs
|
||||
#if defined(CORE_STM32)
|
||||
pinMode(pinMAP, INPUT_ANALOG);
|
||||
pinMode(pinO2, INPUT_ANALOG);
|
||||
pinMode(pinO2_2, INPUT_ANALOG);
|
||||
pinMode(pinTPS, INPUT_ANALOG);
|
||||
pinMode(pinIAT, INPUT_ANALOG);
|
||||
pinMode(pinCLT, INPUT_ANALOG);
|
||||
pinMode(pinBat, INPUT_ANALOG);
|
||||
pinMode(pinBaro, INPUT_ANALOG);
|
||||
#else
|
||||
pinMode(pinMAP, INPUT);
|
||||
pinMode(pinO2, INPUT);
|
||||
pinMode(pinO2_2, INPUT);
|
||||
pinMode(pinTPS, INPUT);
|
||||
pinMode(pinIAT, INPUT);
|
||||
pinMode(pinCLT, INPUT);
|
||||
pinMode(pinBat, INPUT);
|
||||
pinMode(pinBaro, INPUT);
|
||||
#ifndef ARDUINO_ARCH_STM32 //libmaple core aka STM32DUINO
|
||||
pinMode(pinMAP, INPUT_ANALOG);
|
||||
pinMode(pinO2, INPUT_ANALOG);
|
||||
pinMode(pinO2_2, INPUT_ANALOG);
|
||||
pinMode(pinTPS, INPUT_ANALOG);
|
||||
pinMode(pinIAT, INPUT_ANALOG);
|
||||
pinMode(pinCLT, INPUT_ANALOG);
|
||||
pinMode(pinBat, INPUT_ANALOG);
|
||||
pinMode(pinBaro, INPUT_ANALOG);
|
||||
#else
|
||||
pinMode(pinMAP, INPUT);
|
||||
pinMode(pinO2, INPUT);
|
||||
pinMode(pinO2_2, INPUT);
|
||||
pinMode(pinTPS, INPUT);
|
||||
pinMode(pinIAT, INPUT);
|
||||
pinMode(pinCLT, INPUT);
|
||||
pinMode(pinBat, INPUT);
|
||||
pinMode(pinBaro, INPUT);
|
||||
#endif
|
||||
#endif
|
||||
pinMode(pinTrigger, INPUT);
|
||||
pinMode(pinTrigger2, INPUT);
|
||||
|
|
Loading…
Reference in New Issue