Untitled diff
0 removals
618 lines
0 additions
618 lines
/**************************************************************************************/
/**************************************************************************************/
/*************** Motor Pin order ********************/
/*************** Motor Pin order ********************/
/**************************************************************************************/
/**************************************************************************************/
// since we are uing the PWM generation in a direct way, the pin order is just to inizialie the right pins
// since we are uing the PWM generation in a direct way, the pin order is just to inizialie the right pins
// its not possible to change a PWM output pin just by changing the order
// its not possible to change a PWM output pin just by changing the order
#if defined(PROMINI)
#if defined(PROMINI)
uint8_t PWM_PIN[8] = {9,10,11,3,6,5,A2,12}; //for a quad+: rear,right,left,front
uint8_t PWM_PIN[8] = {9,10,11,3,6,5,A2,12}; //for a quad+: rear,right,left,front
#endif
#endif
#if defined(PROMICRO)
#if defined(PROMICRO)
#if !defined(HWPWM6)
#if !defined(HWPWM6)
#if !defined(TEENSY20)
#if !defined(TEENSY20)
uint8_t PWM_PIN[8] = {9,10,5,6,4,A2,A0,A1}; //for a quad+: rear,right,left,front
uint8_t PWM_PIN[8] = {9,10,5,6,4,A2,A0,A1}; //for a quad+: rear,right,left,front
#else
#else
uint8_t PWM_PIN[8] = {14,15,9,12,22,18,16,17}; //for a quad+: rear,right,left,front
uint8_t PWM_PIN[8] = {14,15,9,12,22,18,16,17}; //for a quad+: rear,right,left,front
#endif
#endif
#else
#else
#if !defined(TEENSY20)
#if !defined(TEENSY20)
uint8_t PWM_PIN[8] = {9,10,5,6,11,13,A0,A1}; //for a quad+: rear,right,left,front
uint8_t PWM_PIN[8] = {9,10,5,6,11,13,A0,A1}; //for a quad+: rear,right,left,front
#else
#else
uint8_t PWM_PIN[8] = {14,15,9,12,4,10,16,17}; //for a quad+: rear,right,left,front
uint8_t PWM_PIN[8] = {14,15,9,12,4,10,16,17}; //for a quad+: rear,right,left,front
#endif
#endif
#endif
#endif
#endif
#endif
#if defined(MEGA)
#if defined(MEGA)
uint8_t PWM_PIN[8] = {3,5,6,2,7,8,9,10}; //for a quad+: rear,right,left,front //+ for y6: 7:under right 8:under left
uint8_t PWM_PIN[8] = {3,5,6,2,7,8,9,10}; //for a quad+: rear,right,left,front //+ for y6: 7:under right 8:under left
#endif
#endif
/**************************************************************************************/
/**************************************************************************************/
/*************** Software PWM & Servo variables ********************/
/*************** Software PWM & Servo variables ********************/
/**************************************************************************************/
/**************************************************************************************/
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
#if defined(SERVO)
#if defined(SERVO)
#if defined(AIRPLANE)|| defined(HELICOPTER)
#if defined(AIRPLANE)|| defined(HELICOPTER)
// To prevent motor to start at reset. atomicServo[7]=5 or 249 if reversed servo
// To prevent motor to start at reset. atomicServo[7]=5 or 249 if reversed servo
volatile uint8_t atomicServo[8] = {125,125,125,125,125,125,125,5};
volatile uint8_t atomicServo[8] = {125,125,125,125,125,125,125,5};
#else
#else
volatile uint8_t atomicServo[8] = {125,125,125,125,125,125,125,125};
volatile uint8_t atomicServo[8] = {125,125,125,125,125,125,125,125};
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR > 4)
//for HEX Y6 and HEX6/HEX6X flat for promini
//for HEX Y6 and HEX6/HEX6X flat for promini
volatile uint8_t atomicPWM_PIN5_lowState;
volatile uint8_t atomicPWM_PIN5_lowState;
volatile uint8_t atomicPWM_PIN5_highState;
volatile uint8_t atomicPWM_PIN5_highState;
volatile uint8_t atomicPWM_PIN6_lowState;
volatile uint8_t atomicPWM_PIN6_lowState;
volatile uint8_t atomicPWM_PIN6_highState;
volatile uint8_t atomicPWM_PIN6_highState;
#endif
#endif
#if (NUMBER_MOTOR > 6)
#if (NUMBER_MOTOR > 6)
//for OCTO on promini
//for OCTO on promini
volatile uint8_t atomicPWM_PINA2_lowState;
volatile uint8_t atomicPWM_PINA2_lowState;
volatile uint8_t atomicPWM_PINA2_highState;
volatile uint8_t atomicPWM_PINA2_highState;
volatile uint8_t atomicPWM_PIN12_lowState;
volatile uint8_t atomicPWM_PIN12_lowState;
volatile uint8_t atomicPWM_PIN12_highState;
volatile uint8_t atomicPWM_PIN12_highState;
#endif
#endif
#else
#else
#if defined(SERVO)
#if defined(SERVO)
#if defined(AIRPLANE)|| defined(HELICOPTER)
#if defined(AIRPLANE)|| defined(HELICOPTER)
// To prevent motor to start at reset. atomicServo[7]=5 or 249 if reversed servo
// To prevent motor to start at reset. atomicServo[7]=5 or 249 if reversed servo
volatile uint8_t atomicServo[8] = {8000,8000,8000,8000,8000,8000,8000,8000};
volatile uint8_t atomicServo[8] = {8000,8000,8000,8000,8000,8000,8000,8000};
#else
#else
volatile uint16_t atomicServo[8] = {8000,8000,8000,8000,8000,8000,8000,320};
volatile uint16_t atomicServo[8] = {8000,8000,8000,8000,8000,8000,8000,320};
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR > 4)
//for HEX Y6 and HEX6/HEX6X and for Promicro
//for HEX Y6 and HEX6/HEX6X and for Promicro
volatile uint16_t atomicPWM_PIN5_lowState;
volatile uint16_t atomicPWM_PIN5_lowState;
volatile uint16_t atomicPWM_PIN5_highState;
volatile uint16_t atomicPWM_PIN5_highState;
volatile uint16_t atomicPWM_PIN6_lowState;
volatile uint16_t atomicPWM_PIN6_lowState;
volatile uint16_t atomicPWM_PIN6_highState;
volatile uint16_t atomicPWM_PIN6_highState;
#endif
#endif
#if (NUMBER_MOTOR > 6)
#if (NUMBER_MOTOR > 6)
//for OCTO on Promicro
//for OCTO on Promicro
volatile uint16_t atomicPWM_PINA2_lowState;
volatile uint16_t atomicPWM_PINA2_lowState;
volatile uint16_t atomicPWM_PINA2_highState;
volatile uint16_t atomicPWM_PINA2_highState;
volatile uint16_t atomicPWM_PIN12_lowState;
volatile uint16_t atomicPWM_PIN12_lowState;
volatile uint16_t atomicPWM_PIN12_highState;
volatile uint16_t atomicPWM_PIN12_highState;
#endif
#endif
#endif
#endif
/**************************************************************************************/
/**************************************************************************************/
/*************** Writes the Servos values to the needed format ********************/
/*************** Writes the Servos values to the needed format ********************/
/**************************************************************************************/
/**************************************************************************************/
void writeServos() {
void writeServos() {
#if defined(SERVO)
#if defined(SERVO)
#if defined(PRI_SERVO_FROM) // write primary servos
#if defined(PRI_SERVO_FROM) // write primary servos
for(uint8_t i = (PRI_SERVO_FROM-1); i < PRI_SERVO_TO; i++){
for(uint8_t i = (PRI_SERVO_FROM-1); i < PRI_SERVO_TO; i++){
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
atomicServo[i] = (servo[i]-1000)>>2;
atomicServo[i] = (servo[i]-1000)>>2;
#else
#else
atomicServo[i] = (servo[i]-1000)<<4;
atomicServo[i] = (servo[i]-1000)<<4;
#endif
#endif
}
}
#endif
#endif
#if defined(SEC_SERVO_FROM) // write secundary servos
#if defined(SEC_SERVO_FROM) // write secundary servos
#if defined(SERVO_TILT) && defined(MMSERVOGIMBAL)
#if defined(SERVO_TILT) && defined(MMSERVOGIMBAL)
// Moving Average Servo Gimbal by Magnetron1
// Moving Average Servo Gimbal by Magnetron1
static int16_t mediaMobileServoGimbalADC[3][MMSERVOGIMBALVECTORLENGHT];
static int16_t mediaMobileServoGimbalADC[3][MMSERVOGIMBALVECTORLENGHT];
static int32_t mediaMobileServoGimbalADCSum[3];
static int32_t mediaMobileServoGimbalADCSum[3];
static uint8_t mediaMobileServoGimbalIDX;
static uint8_t mediaMobileServoGimbalIDX;
uint8_t axis;
uint8_t axis;
mediaMobileServoGimbalIDX = ++mediaMobileServoGimbalIDX % MMSERVOGIMBALVECTORLENGHT;
mediaMobileServoGimbalIDX = ++mediaMobileServoGimbalIDX % MMSERVOGIMBALVECTORLENGHT;
for (axis=(SEC_SERVO_FROM-1); axis < SEC_SERVO_TO; axis++) {
for (axis=(SEC_SERVO_FROM-1); axis < SEC_SERVO_TO; axis++) {
mediaMobileServoGimbalADCSum[axis] -= mediaMobileServoGimbalADC[axis][mediaMobileServoGimbalIDX];
mediaMobileServoGimbalADCSum[axis] -= mediaMobileServoGimbalADC[axis][mediaMobileServoGimbalIDX];
mediaMobileServoGimbalADC[axis][mediaMobileServoGimbalIDX] = servo[axis];
mediaMobileServoGimbalADC[axis][mediaMobileServoGimbalIDX] = servo[axis];
mediaMobileServoGimbalADCSum[axis] += mediaMobileServoGimbalADC[axis][mediaMobileServoGimbalIDX];
mediaMobileServoGimbalADCSum[axis] += mediaMobileServoGimbalADC[axis][mediaMobileServoGimbalIDX];
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
atomicServo[axis] = (mediaMobileServoGimbalADCSum[axis] / MMSERVOGIMBALVECTORLENGHT - 1000)>>2;
atomicServo[axis] = (mediaMobileServoGimbalADCSum[axis] / MMSERVOGIMBALVECTORLENGHT - 1000)>>2;
#else
#else
atomicServo[axis] = (mediaMobileServoGimbalADCSum[axis] / MMSERVOGIMBALVECTORLENGHT - 1000)<<4;
atomicServo[axis] = (mediaMobileServoGimbalADCSum[axis] / MMSERVOGIMBALVECTORLENGHT - 1000)<<4;
#endif
#endif
}
}
#else
#else
for(uint8_t i = (SEC_SERVO_FROM-1); i < SEC_SERVO_TO; i++){
for(uint8_t i = (SEC_SERVO_FROM-1); i < SEC_SERVO_TO; i++){
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6))
atomicServo[i] = (servo[i]-1000)>>2;
atomicServo[i] = (servo[i]-1000)>>2;
#else
#else
atomicServo[i] = (servo[i]-1000)<<4;
atomicServo[i] = (servo[i]-1000)<<4;
#endif
#endif
}
}
#endif
#endif
#endif
#endif
#endif
#endif
}
}
/**************************************************************************************/
/**************************************************************************************/
/************ Writes the Motors values to the PWM compare register ******************/
/************ Writes the Motors values to the PWM compare register ******************/
/**************************************************************************************/
/**************************************************************************************/
void writeMotors() { // [1000;2000] => [125;250]
void writeMotors() { // [1000;2000] => [125;250]
/**************** Specific PWM Timers & Registers for the MEGA's *******************/
/**************** Specific PWM Timers & Registers for the MEGA's *******************/
#if defined(MEGA)// [1000:2000] => [8000:16000] for timer 3 & 4 for mega
#if defined(MEGA)// [1000:2000] => [8000:16000] for timer 3 & 4 for mega
#if (NUMBER_MOTOR > 0)
#if (NUMBER_MOTOR > 0)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR3C = motor[0]<<3; // pin 3
OCR3C = motor[0]<<3; // pin 3
#else
#else
OCR3C = ((motor[0]<<4) - 16000) + 128;
OCR3C = ((motor[0]<<4) - 16000) + 128;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 1)
#if (NUMBER_MOTOR > 1)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR3A = motor[1]<<3; // pin 5
OCR3A = motor[1]<<3; // pin 5
#else
#else
OCR3A = ((motor[1]<<4) - 16000) + 128;
OCR3A = ((motor[1]<<4) - 16000) + 128;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 2)
#if (NUMBER_MOTOR > 2)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR4A = motor[2]<<3; // pin 6
OCR4A = motor[2]<<3; // pin 6
#else
#else
OCR4A = ((motor[2]<<4) - 16000) + 128;
OCR4A = ((motor[2]<<4) - 16000) + 128;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 3)
#if (NUMBER_MOTOR > 3)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR3B = motor[3]<<3; // pin 2
OCR3B = motor[3]<<3; // pin 2
#else
#else
OCR3B = ((motor[3]<<4) - 16000) + 128;
OCR3B = ((motor[3]<<4) - 16000) + 128;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR > 4)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR4B = motor[4]<<3; // pin 7
OCR4B = motor[4]<<3; // pin 7
OCR4C = motor[5]<<3; // pin 8
OCR4C = motor[5]<<3; // pin 8
#else
#else
OCR4B = ((motor[4]<<4) - 16000) + 128;
OCR4B = ((motor[4]<<4) - 16000) + 128;
OCR4C = ((motor[5]<<4) - 16000) + 128;
OCR4C = ((motor[5]<<4) - 16000) + 128;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 6)
#if (NUMBER_MOTOR > 6)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR2B = motor[6]>>3; // pin 9
OCR2B = motor[6]>>3; // pin 9
OCR2A = motor[7]>>3; // pin 10
OCR2A = motor[7]>>3; // pin 10
#else
#else
OCR2B = ((motor[6]>>2) - 250) + 2);
OCR2B = ((motor[6]>>2) - 250) + 2);
OCR2A = ((motor[7]>>2) - 250) + 2);
OCR2A = ((motor[7]>>2) - 250) + 2);
#endif
#endif
#endif
#endif
#endif
#endif
/******** Specific PWM Timers & Registers for the atmega32u4 (Promicro) ************/
/******** Specific PWM Timers & Registers for the atmega32u4 (Promicro) ************/
#if defined(PROMICRO)
#if defined(PROMICRO)
#if (NUMBER_MOTOR > 0) // Timer 1 A & B [1000:2000] => [8000:16000]
#if (NUMBER_MOTOR > 0) // Timer 1 A & B [1000:2000] => [8000:16000]
OCR1A = motor[0]<<3; // pin 9
OCR1A = motor[0]<<3; // pin 9
#endif
#endif
#if (NUMBER_MOTOR > 1)
#if (NUMBER_MOTOR > 1)
OCR1B = motor[1]<<3; // pin 10
OCR1B = motor[1]<<3; // pin 10
#endif
#endif
#if (NUMBER_MOTOR > 2) // Timer 4 A & D [1000:2000] => [1000:2000]
#if (NUMBER_MOTOR > 2) // Timer 4 A & D [1000:2000] => [1000:2000]
#if !defined(HWPWM6)
#if !defined(HWPWM6)
// to write values > 255 to timer 4 A/B we need to split the bytes
// to write values > 255 to timer 4 A/B we need to split the bytes
TC4H = (2047-motor[2])>>8; OCR4A = ((2047-motor[2])&0xFF); // pin 5
TC4H = (2047-motor[2])>>8; OCR4A = ((2047-motor[2])&0xFF); // pin 5
#else
#else
OCR3A = motor[2]<<3; // pin 5
OCR3A = motor[2]<<3; // pin 5
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 3)
#if (NUMBER_MOTOR > 3)
TC4H = motor[3]>>8; OCR4D = (motor[3]&0xFF); // pin 6
TC4H = motor[3]>>8; OCR4D = (motor[3]&0xFF); // pin 6
#endif
#endif
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR > 4)
#if !defined(HWPWM6)
#if !defined(HWPWM6)
#if (NUMBER_MOTOR == 6) && !defined(SERVO)
#if (NUMBER_MOTOR == 6) && !defined(SERVO)
atomicPWM_PIN5_highState = motor[4]<<3;
atomicPWM_PIN5_highState = motor[4]<<3;
atomicPWM_PIN5_lowState = 16383-atomicPWM_PIN5_highState;
atomicPWM_PIN5_lowState = 16383-atomicPWM_PIN5_highState;
atomicPWM_PIN6_highState = motor[5]<<3;
atomicPWM_PIN6_highState = motor[5]<<3;
atomicPWM_PIN6_lowState = 16383-atomicPWM_PIN6_highState;
atomicPWM_PIN6_lowState = 16383-atomicPWM_PIN6_highState;
#else
#else
atomicPWM_PIN5_highState = ((motor[4]-1000)<<4)+320;
atomicPWM_PIN5_highState = ((motor[4]-1000)<<4)+320;
atomicPWM_PIN5_lowState = 15743-atomicPWM_PIN5_highState;
atomicPWM_PIN5_lowState = 15743-atomicPWM_PIN5_highState;
atomicPWM_PIN6_highState = ((motor[5]-1000)<<4)+320;
atomicPWM_PIN6_highState = ((motor[5]-1000)<<4)+320;
atomicPWM_PIN6_lowState = 15743-atomicPWM_PIN6_highState;
atomicPWM_PIN6_lowState = 15743-atomicPWM_PIN6_highState;
#endif
#endif
#else
#else
OCR1C = motor[4]<<3; // pin 11
OCR1C = motor[4]<<3; // pin 11
TC4H = motor[5]>>8; OCR4A = (motor[5]&0xFF); // pin 13
TC4H = motor[5]>>8; OCR4A = (motor[5]&0xFF); // pin 13
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 6)
#if (NUMBER_MOTOR > 6)
#if !defined(HWPWM6)
#if !defined(HWPWM6)
atomicPWM_PINA2_highState = ((motor[6]-1000)<<4)+320;
atomicPWM_PINA2_highState = ((motor[6]-1000)<<4)+320;
atomicPWM_PINA2_lowState = 15743-atomicPWM_PINA2_highState;
atomicPWM_PINA2_lowState = 15743-atomicPWM_PINA2_highState;
atomicPWM_PIN12_highState = ((motor[7]-1000)<<4)+320;
atomicPWM_PIN12_highState = ((motor[7]-1000)<<4)+320;
atomicPWM_PIN12_lowState = 15743-atomicPWM_PIN12_highState;
atomicPWM_PIN12_lowState = 15743-atomicPWM_PIN12_highState;
#else
#else
atomicPWM_PINA2_highState = ((motor[6]-1000)>>2)+5;
atomicPWM_PINA2_highState = ((motor[6]-1000)>>2)+5;
atomicPWM_PINA2_lowState = 245-atomicPWM_PINA2_highState;
atomicPWM_PINA2_lowState = 245-atomicPWM_PINA2_highState;
atomicPWM_PIN12_highState = ((motor[7]-1000)>>2)+5;
atomicPWM_PIN12_highState = ((motor[7]-1000)>>2)+5;
atomicPWM_PIN12_lowState = 245-atomicPWM_PIN12_highState;
atomicPWM_PIN12_lowState = 245-atomicPWM_PIN12_highState;
#endif
#endif
#endif
#endif
#endif
#endif
/******** Specific PWM Timers & Registers for the atmega328P (Promini) ************/
/******** Specific PWM Timers & Registers for the atmega328P (Promini) ************/
#if defined(PROMINI)
#if defined(PROMINI)
#if (NUMBER_MOTOR > 0)
#if (NUMBER_MOTOR > 0)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR1A = motor[0]>>3; // pin 9
OCR1A = motor[0]>>3; // pin 9
#else
#else
OCR1A = ((motor[0]>>2) - 250) + 2;
OCR1A = ((motor[0]>>2) - 250) + 2;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 1)
#if (NUMBER_MOTOR > 1)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR1B = motor[1]>>3; // pin 10
OCR1B = motor[1]>>3; // pin 10
#else
#else
OCR1B = ((motor[1]>>2) - 250) + 2;
OCR1B = ((motor[1]>>2) - 250) + 2;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 2)
#if (NUMBER_MOTOR > 2)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR2A = motor[2]>>3; // pin 11
OCR2A = motor[2]>>3; // pin 11
#else
#else
OCR2A = ((motor[2]>>2) - 250) + 2;
OCR2A = ((motor[2]>>2) - 250) + 2;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 3)
#if (NUMBER_MOTOR > 3)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
OCR2B = motor[3]>>3; // pin 3
OCR2B = motor[3]>>3; // pin 3
#else
#else
OCR2B = ((motor[3]>>2) - 250) + 2;
OCR2B = ((motor[3]>>2) - 250) + 2;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR == 6) && !defined(SERVO)
#if (NUMBER_MOTOR == 6) && !defined(SERVO)
#ifndef EXT_MOTOR_RANGE
#ifndef EXT_MOTOR_RANGE
atomicPWM_PIN6_highState = motor[4]>>3;
atomicPWM_PIN6_highState = motor[4]>>3;
atomicPWM_PIN5_highState = motor[5]>>3;
atomicPWM_PIN5_highState = motor[5]>>3;
#else
#else
atomicPWM_PIN6_highState = ((motor[4]>>2) - 250) + 2;
atomicPWM_PIN6_highState = ((motor[4]>>2) - 250) + 2;
atomicPWM_PIN5_highState = ((motor[5]>>2) - 250) + 2;
atomicPWM_PIN5_highState = ((motor[5]>>2) - 250) + 2;
#endif
#endif
atomicPWM_PIN6_lowState = 255-atomicPWM_PIN6_highState;
atomicPWM_PIN6_lowState = 255-atomicPWM_PIN6_highState;
atomicPWM_PIN5_lowState = 255-atomicPWM_PIN5_highState;
atomicPWM_PIN5_lowState = 255-atomicPWM_PIN5_highState;
#else //note: EXT_MOTOR_RANGE not possible here
#else //note: EXT_MOTOR_RANGE not possible here
atomicPWM_PIN6_highState = ((motor[4]-1000)>>2)+5;
atomicPWM_PIN6_highState = ((motor[4]-1000)>>2)+5;
atomicPWM_PIN6_lowState = 245-atomicPWM_PIN6_highState;
atomicPWM_PIN6_lowState = 245-atomicPWM_PIN6_highState;
atomicPWM_PIN5_highState = ((motor[5]-1000)>>2)+5;
atomicPWM_PIN5_highState = ((motor[5]-1000)>>2)+5;
atomicPWM_PIN5_lowState = 245-atomicPWM_PIN5_highState;
atomicPWM_PIN5_lowState = 245-atomicPWM_PIN5_highState;
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 6) //note: EXT_MOTOR_RANGE not possible here
#if (NUMBER_MOTOR > 6) //note: EXT_MOTOR_RANGE not possible here
atomicPWM_PINA2_highState = ((motor[6]-1000)>>2)+5;
atomicPWM_PINA2_highState = ((motor[6]-1000)>>2)+5;
atomicPWM_PINA2_lowState = 245-atomicPWM_PINA2_highState;
atomicPWM_PINA2_lowState = 245-atomicPWM_PINA2_highState;
atomicPWM_PIN12_highState = ((motor[7]-1000)>>2)+5;
atomicPWM_PIN12_highState = ((motor[7]-1000)>>2)+5;
atomicPWM_PIN12_lowState = 245-atomicPWM_PIN12_highState;
atomicPWM_PIN12_lowState = 245-atomicPWM_PIN12_highState;
#endif
#endif
#endif
#endif
}
}
/**************************************************************************************/
/**************************************************************************************/
/************ Writes the mincommand to all Motors ******************/
/************ Writes the mincommand to all Motors ******************/
/**************************************************************************************/
/**************************************************************************************/
void writeAllMotors(int16_t mc) { // Sends commands to all motors
void writeAllMotors(int16_t mc) { // Sends commands to all motors
for (uint8_t i =0;i<NUMBER_MOTOR;i++)
for (uint8_t i =0;i<NUMBER_MOTOR;i++)
motor[i]=mc;
motor[i]=mc;
writeMotors();
writeMotors();
}
}
/**************************************************************************************/
/**************************************************************************************/
/************ Initialize the PWM Timers and Registers ******************/
/************ Initialize the PWM Timers and Registers ******************/
/**************************************************************************************/
/**************************************************************************************/
void initOutput() {
void initOutput() {
/**************** mark all PWM pins as Output ******************/
/**************** mark all PWM pins as Output ******************/
for(uint8_t i=0;i<NUMBER_MOTOR;i++)
for(uint8_t i=0;i<NUMBER_MOTOR;i++)
pinMode(PWM_PIN[i],OUTPUT);
pinMode(PWM_PIN[i],OUTPUT);
/**************** Specific PWM Timers & Registers for the MEGA's ******************/
/**************** Specific PWM Timers & Registers for the MEGA's ******************/
#if defined(MEGA)
#if defined(MEGA)
#if (NUMBER_MOTOR > 0)
#if (NUMBER_MOTOR > 0)
// init 16bit timer 3
// init 16bit timer 3
TCCR3A |= (1<<WGM31); // phase correct mode
TCCR3A |= (1<<WGM31); // phase correct mode
TCCR3A &= ~(1<<WGM30);
TCCR3A &= ~(1<<WGM30);
TCCR3B |= (1<<WGM33);
TCCR3B |= (1<<WGM33);
TCCR3B &= ~(1<<CS31); // no prescaler
TCCR3B &= ~(1<<CS31); // no prescaler
ICR3 |= 0x3FFF; // TOP to 16383;
ICR3 |= 0x3FFF; // TOP to 16383;
TCCR3A |= _BV(COM3C1); // connect pin 3 to timer 3 channel C
TCCR3A |= _BV(COM3C1); // connect pin 3 to timer 3 channel C
#endif
#endif
#if (NUMBER_MOTOR > 1)
#if (NUMBER_MOTOR > 1)
TCCR3A |= _BV(COM3A1); // connect pin 5 to timer 3 channel A
TCCR3A |= _BV(COM3A1); // connect pin 5 to timer 3 channel A
#endif
#endif
#if (NUMBER_MOTOR > 2)
#if (NUMBER_MOTOR > 2)
// init 16bit timer 4
// init 16bit timer 4
TCCR4A |= (1<<WGM41); // phase correct mode
TCCR4A |= (1<<WGM41); // phase correct mode
TCCR4A &= ~(1<<WGM40);
TCCR4A &= ~(1<<WGM40);
TCCR4B |= (1<<WGM43);
TCCR4B |= (1<<WGM43);
TCCR4B &= ~(1<<CS41); // no prescaler
TCCR4B &= ~(1<<CS41); // no prescaler
ICR4 |= 0x3FFF; // TOP to 16383;
ICR4 |= 0x3FFF; // TOP to 16383;
TCCR4A |= _BV(COM4A1); // connect pin 6 to timer 4 channel A
TCCR4A |= _BV(COM4A1); // connect pin 6 to timer 4 channel A
#endif
#endif
#if (NUMBER_MOTOR > 3)
#if (NUMBER_MOTOR > 3)
TCCR3A |= _BV(COM3B1); // connect pin 2 to timer 3 channel B
TCCR3A |= _BV(COM3B1); // connect pin 2 to timer 3 channel B
#endif
#endif
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR > 4)
TCCR4A |= _BV(COM4B1); // connect pin 7 to timer 4 channel B
TCCR4A |= _BV(COM4B1); // connect pin 7 to timer 4 channel B
TCCR4A |= _BV(COM4C1); // connect pin 8 to timer 4 channel C
TCCR4A |= _BV(COM4C1); // connect pin 8 to timer 4 channel C
#endif
#endif
#if (NUMBER_MOTOR > 6)
#if (NUMBER_MOTOR > 6)
// timer 2 is a 8bit timer so we cant change its range
// timer 2 is a 8bit timer so we cant change its range
TCCR2A |= _BV(COM2B1); // connect pin 9 to timer 2 channel B
TCCR2A |= _BV(COM2B1); // connect pin 9 to timer 2 channel B
TCCR2A |= _BV(COM2A1); // connect pin 10 to timer 2 channel A
TCCR2A |= _BV(COM2A1); // connect pin 10 to timer 2 channel A
#endif
#endif
#endif
#endif
/******** Specific PWM Timers & Registers for the atmega32u4 (Promicro) ************/
/******** Specific PWM Timers & Registers for the atmega32u4 (Promicro) ************/
#if defined(PROMICRO)
#if defined(PROMICRO)
#if (NUMBER_MOTOR > 0)
#if (NUMBER_MOTOR > 0)
TCCR1A |= (1<<WGM11); // phase correct mode & no prescaler
TCCR1A |= (1<<WGM11); // phase correct mode & no prescaler
TCCR1A &= ~(1<<WGM10);
TCCR1A &= ~(1<<WGM10);
TCCR1B &= ~(1<<WGM12) & ~(1<<CS11) & ~(1<<CS12);
TCCR1B &= ~(1<<WGM12) & ~(1<<CS11) & ~(1<<CS12);
TCCR1B |= (1<<WGM13) | (1<<CS10);
TCCR1B |= (1<<WGM13) | (1<<CS10);
ICR1 |= 0x3FFF; // TOP to 16383;
ICR1 |= 0x3FFF; // TOP to 16383;
TCCR1A |= _BV(COM1A1); // connect pin 9 to timer 1 channel A
TCCR1A |= _BV(COM1A1); // connect pin 9 to timer 1 channel A
#endif
#endif
#if (NUMBER_MOTOR > 1)
#if (NUMBER_MOTOR > 1)
TCCR1A |= _BV(COM1B1); // connect pin 10 to timer 1 channel B
TCCR1A |= _BV(COM1B1); // connect pin 10 to timer 1 channel B
#endif
#endif
#if (NUMBER_MOTOR > 2)
#if (NUMBER_MOTOR > 2)
#if !defined(HWPWM6) // timer 4A
#if !defined(HWPWM6) // timer 4A
TCCR4E |= (1<<ENHC4); // enhanced pwm mode
TCCR4E |= (1<<ENHC4); // enhanced pwm mode
TCCR4B &= ~(1<<CS41); TCCR4B |= (1<<CS42)|(1<<CS40); // prescaler to 16
TCCR4B &= ~(1<<CS41); TCCR4B |= (1<<CS42)|(1<<CS40); // prescaler to 16
TCCR4D |= (1<<WGM40); TC4H = 0x3; OCR4C = 0xFF; // phase and frequency correct mode & top to 1023 but with enhanced pwm mode we have 2047
TCCR4D |= (1<<WGM40); TC4H = 0x3; OCR4C = 0xFF; // phase and frequency correct mode & top to 1023 but with enhanced pwm mode we have 2047
TCCR4A |= (1<<COM4A0)|(1<<PWM4A); // connect pin 5 to timer 4 channel A
TCCR4A |= (1<<COM4A0)|(1<<PWM4A); // connect pin 5 to timer 4 channel A
#else // timer 3A
#else // timer 3A
TCCR3A |= (1<<WGM31); // phase correct mode & no prescaler
TCCR3A |= (1<<WGM31); // phase correct mode & no prescaler
TCCR3A &= ~(1<<WGM30);
TCCR3A &= ~(1<<WGM30);
TCCR3B &= ~(1<<WGM32) & ~(1<<CS31) & ~(1<<CS32);
TCCR3B &= ~(1<<WGM32) & ~(1<<CS31) & ~(1<<CS32);
TCCR3B |= (1<<WGM33) | (1<<CS30);
TCCR3B |= (1<<WGM33) | (1<<CS30);
ICR3 |= 0x3FFF; // TOP to 16383;
ICR3 |= 0x3FFF; // TOP to 16383;
TCCR3A |= _BV(COM3A1); // connect pin 5 to timer 3 channel A
TCCR3A |= _BV(COM3A1); // connect pin 5 to timer 3 channel A
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 3)
#if (NUMBER_MOTOR > 3)
#if defined(HWPWM6)
#if defined(HWPWM6)
TCCR4E |= (1<<ENHC4); // enhanced pwm mode
TCCR4E |= (1<<ENHC4); // enhanced pwm mode
TCCR4B &= ~(1<<CS41); TCCR4B |= (1<<CS42)|(1<<CS40); // prescaler to 16
TCCR4B &= ~(1<<CS41); TCCR4B |= (1<<CS42)|(1<<CS40); // prescaler to 16
TCCR4D |= (1<<WGM40); TC4H = 0x3; OCR4C = 0xFF; // phase and frequency correct mode & top to 1023 but with enhanced pwm mode we have 2047
TCCR4D |= (1<<WGM40); TC4H = 0x3; OCR4C = 0xFF; // phase and frequency correct mode & top to 1023 but with enhanced pwm mode we have 2047
#endif
#endif
TCCR4C |= (1<<COM4D1)|(1<<PWM4D); // connect pin 6 to timer 4 channel D
TCCR4C |= (1<<COM4D1)|(1<<PWM4D); // connect pin 6 to timer 4 channel D
#endif
#endif
#if (NUMBER_MOTOR > 4)
#if (NUMBER_MOTOR > 4)
#if defined(HWPWM6)
#if defined(HWPWM6)
TCCR1A |= _BV(COM1C1); // connect pin 11 to timer 1 channel C
TCCR1A |= _BV(COM1C1); // connect pin 11 to timer 1 channel C
TCCR4A |= (1<<COM4A1)|(1<<PWM4A); // connect pin 13 to timer 4 channel A
TCCR4A |= (1<<COM4A1)|(1<<PWM4A); // connect pin 13 to timer 4 channel A
#else
#else
initializeSoftPWM();
initializeSoftPWM();
#endif
#endif
#endif
#endif
#if (NUMBER_MOTOR > 6)
#if (NUMBER_MOTOR > 6)
#if defined(HWPWM6)
#if defined(HWPWM6)
initializeSoftPWM();
initializeSoftPWM();
#endif
#endif
#endif
#endif
#endif
#endif
/******** Specific PWM Timers & Registers for the atmega328P (Promini) ************/
/******** Specific PWM Timers & Registers for the atmega328P (Promini) ************/
#if defined(PROMINI)
#if defined(PROMINI)
#if (NUMBER_MOTOR > 0)
#if (NUMBER_MOTOR > 0)
TCCR1A |= _BV(COM1A1); // connect pin 9 to timer 1 channel A
TCCR1A |= _BV(COM1A1); // connect pin 9 to timer 1 channel A
#endif
#endif
#if (NUMBER_MOTOR > 1)
#if (NUMBER_MOTOR > 1)
TCCR1A |= _BV(COM1B1); // connect pin 10 to timer 1 channel B
TCCR1A |= _BV(COM1B1); // connect pin 10 to timer 1 channel B
#endif
#endif
#if (NUMBER_MOTOR > 2)
#if (NUMBER_MOTOR > 2)
TCCR2A |= _BV(COM2A1); // connect pin 11 to timer 2 channel A
TCCR2A |= _BV(COM2A1); // connect pin 11 to timer 2 channel A
#endif
#endif
#if (NUMBER_MOTOR > 3)
#if (NUMBER_MOTOR > 3)
TCCR2A |= _BV(COM2B1); // connect pin 3 to timer 2 channel B
TCCR2A |= _BV(COM2B1); // connect pin 3 to timer 2 channel B
#endif
#endif
#if (NUMBER_MOTOR > 5) // PIN 5 & 6 or A0 & A1
#if (NUMBER_MOTOR > 5) // PIN 5 & 6 or A0 & A1
initializeSoftPWM();
initializeSoftPWM();
#if defined(A0_A1_PIN_HEX) || (NUMBER_MOTOR > 6)
#if defined(A0_A1_PIN_HEX) || (NUMBER_MOTOR > 6)
pinMode(5,INPUT);pinMode(6,INPUT); // we reactivate the INPUT affectation for these two PINs
pinMode(5,INPUT);pinMode(6,INPUT); // we reactivate the INPUT affectation for these two PINs
pinMode(A0,OUTPUT);pinMode(A1,OUTPUT);
pinMode(A0,OUTPUT);pinMode(A1,OUTPUT);
#endif
#endif
#endif
#endif
#endif
#endif
writeAllMotors(MINCOMMAND);
writeAllMotors(MINCOMMAND);
delay(300);
delay(300);
#if defined(SERVO)
#if defined(SERVO)
initializeServo();
initializeServo();
#endif
#endif
}
}
#if defined(SERVO)
#if defined(SERVO)
/**************************************************************************************/
/**************************************************************************************/
/************ Initialize the PWM Servos ******************/
/************ Initialize the PWM Servos ******************/
/**************************************************************************************/
/**************************************************************************************/
void initializeServo() {
void initializeServo() {
#if (PRI_SERVO_FROM == 1) || (SEC_SERVO_FROM == 1)
#if (PRI_SERVO_FROM == 1) || (SEC_SERVO_FROM == 1)
SERVO_1_PINMODE;
SERVO_1_PINMODE;
#endif
#endif
#if (PRI_SERVO_FROM <= 2 && PRI_SERVO_TO >= 2) || (SEC_SERVO_FROM <= 2 && SEC_SERVO_TO >= 2)
#if (PRI_SERVO_FROM <= 2 && PRI_SERVO_TO >= 2) || (SEC_SERVO_FROM <= 2 && SEC_SERVO_TO >= 2)
SERVO_2_PINMODE;
SERVO_2_PINMODE;
#endif
#endif
#if (PRI_SERVO_FROM <= 3 && PRI_SERVO_TO >= 3) || (SEC_SERVO_FROM <= 3 && SEC_SERVO_TO >= 3)
#if (PRI_SERVO_FROM <= 3 && PRI_SERVO_TO >= 3) || (SEC_SERVO_FROM <= 3 && SEC_SERVO_TO >= 3)
SERVO_3_PINMODE;
SERVO_3_PINMODE;
#endif
#endif
#if (PRI_SERVO_FROM <= 4 && PRI_SERVO_TO >= 4) || (SEC_SERVO_FROM <= 4 && SEC_SERVO_TO >= 4)
#if (PRI_SERVO_FROM <= 4 && PRI_SERVO_TO >= 4) || (SEC_SERVO_FROM <= 4 && SEC_SERVO_TO >= 4)
SERVO_4_PINMODE;
SERVO_4_PINMODE;
#endif
#endif
#if (PRI_SERVO_FROM <= 5 && PRI_SERVO_TO >= 5) || (SEC_SERVO_FROM <= 5 && SEC_SERVO_TO >= 5)
#if (PRI_SERVO_FROM <= 5 && PRI_SERVO_TO >= 5) || (SEC_SERVO_FROM <= 5 && SEC_SERVO_TO >= 5)
SERVO_5_PINMODE;
SERVO_5_PINMODE;
#endif
#endif
#if (PRI_SERVO_FROM <= 6 && PRI_SERVO_TO >= 6) || (SEC_SERVO_FROM <= 6 && SEC_SERVO_TO >= 6)
#if (PRI_SERVO_FROM <= 6 && PRI_SERVO_TO >= 6) || (SEC_SERVO_FROM <= 6 && SEC_SERVO_TO >= 6)
SERVO_6_PINMODE;
SERVO_6_PINMODE;
#endif
#endif
#if (PRI_SERVO_FROM <= 7 && PRI_SERVO_TO >= 7) || (SEC_SERVO_FROM <= 7 && SEC_SERVO_TO >= 7)
#if (PRI_SERVO_FROM <= 7 && PRI_SERVO_TO >= 7) || (SEC_SERVO_FROM <= 7 && SEC_SERVO_TO >= 7)
SERVO_7_PINMODE;
SERVO_7_PINMODE;
#endif
#endif
#if (PRI_SERVO_FROM <= 8 && PRI_SERVO_TO >= 8) || (SEC_SERVO_FROM <= 8 && SEC_SERVO_TO >= 8)
#if (PRI_SERVO_FROM <= 8 && PRI_SERVO_TO >= 8) || (SEC_SERVO_FROM <= 8 && SEC_SERVO_TO >= 8)
SERVO_8_PINMODE;
SERVO_8_PINMODE;
#endif
#endif
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6)) // uses timer 0 Comperator A (8 bit)
#if defined(PROMINI) || (defined(PROMICRO) && defined(HWPWM6)) // uses timer 0 Comperator A (8 bit)
TCCR0A = 0; // normal counting mode
TCCR0A = 0; // normal counting mode
TIMSK0 |= (1<<OCIE0A); // Enable CTC interrupt
TIMSK0 |= (1<<OCIE0A); // Enable CTC interrupt
#define SERVO_ISR TIMER0_COMPA_vect
#define SERVO_ISR TIMER0_COMPA_vect
#define SERVO_CHANNEL OCR0A
#define SERVO_CHANNEL OCR0A
#define SERVO_1K_US 250
#define SERVO_1K_US 250
#endif
#endif
#if (defined(PROMICRO) && !defined(HWPWM6)) // uses timer 3 Comperator A (11 bit)
#if (defined(PROMICRO) && !defined(HWPWM6)) // uses timer 3 Comperator A (11 bit)
TCCR3A &= ~(1<<WGM30) & ~(1<<WGM31); //normal counting & no prescaler
TCCR3A &= ~(1<<WGM30) & ~(1<<WGM31); //normal counting & no prescaler
TCCR3B &= ~(1<<WGM32) & ~(1<<CS31) & ~(1<<CS32) & ~(1<<WGM33);
TCCR3B &= ~(1<<WGM32) & ~(1<<CS31) & ~(1<<CS32) & ~(1<<WGM33);
TCCR3B |= (1<<CS30);
TCCR3B |= (1<<CS30);
TIMSK3 |= (1<<OCIE3A); // Enable CTC interrupt
TIMSK3 |= (1<<OCIE3A); // Enable CTC interrupt
#define SERVO_ISR TIMER3_COMPA_vect
#define SERVO_ISR TIMER3_COMPA_vect
#define SERVO_CHANNEL OCR3A
#define SERVO_CHANNEL OCR3A
#define SERVO_1K_US 16000
#define SERVO_1K_US 16000
#endif
#endif
#if defined(MEGA) // uses timer 5 Comperator A (11 bit)
#if defined(MEGA) // uses timer 5 Comperator A (11 bit)
TCCR5A &= ~(1<<WGM50) & ~(1<<WGM51); //normal counting & no prescaler
TCCR5A &= ~(1<<WGM50) & ~(1<<WGM51); //normal counting & no prescaler
TCCR5B &= ~(1<<WGM52) & ~(1<<CS51) & ~(1<<CS52) & ~(1<<WGM53);
TCCR5B &= ~(1<<WGM52) & ~(1<<CS51) & ~(1<<CS52) & ~(1<<WGM53);
TCCR5B |= (1<<CS50);
TCCR5B |= (1<<CS50);
TIMSK5 |= (1<<OCIE5A); // Enable CTC interrupt
TIMSK5 |= (1<<OCIE5A); // Enable CTC interrupt
#define SERVO_ISR TIMER5_COMPA_vect
#define SERVO_ISR TIMER5_COMPA_vect
#define SERVO_CHANNEL OCR5A
#define SERVO_CHANNEL OCR5A
#define SERVO_1K_US 16000
#define SERVO_1K_US 16000
#endif
#endif
}
}
/**************************************************************************************/
/**************************************************************************************/
/************ Servo software PWM generation ******************/
/************ Servo software PWM generation ******************/
/**************************************************************************************/
/**************************************************************************************/
// prescaler is set by default to 64 on Timer0
// prescaler is set by default to 64 on Timer0
// Duemilanove : 16MHz / 64 => 4 us
// Duemilanove : 16MHz / 64 => 4 us
// 256 steps = 1 counter cycle = 1024 us
// 256 steps = 1 counter cycle = 1024 us
// for servo 2-8
// for servo 2-8
// its almost the same as for servo 1
// its almost the same as for servo 1
#define SERVO_PULSE(PIN_HIGH,ACT_STATE,SERVO_NUM,LAST_PIN_LOW) \
#define SERVO_PULSE(PIN_HIGH,ACT_STATE,SERVO_NUM,LAST_PIN_LOW) \
}else if(state == ACT_STATE){ \
}else if(state == ACT_STATE){ \
LAST_PIN_LOW; \
LAST_PIN_LOW; \
PIN_HIGH; \
PIN_HIGH; \
SERVO_CHANNEL+=SERVO_1K_US; \
SERVO_CHANNEL+=SERVO_1K_US; \
state++; \
state++; \
}else if(state == ACT_STATE+1){ \
}else if(state == ACT_STATE+1){ \
SERVO_CHANNEL+=atomicServo[SERVO_NUM]; \
SERVO_CHANNEL+=atomicServo[SERVO_NUM]; \
state++; \
state++; \
ISR(SERVO_ISR) {
ISR(SERVO_ISR) {
static uint8_t state = 0; // indicates the current state of the chain
static uint8_t state = 0; // indicates the current state of the chain
if(state == 0){
if(state == 0){
SERVO_1_HIGH; // set servo 1's pin high
SERVO_1_HIGH; // set servo 1's pin high
SERVO_CHANNEL+=SERVO_1K_US; // wait 1000us
SERVO_CHANNEL+=SERVO_1K_US; // wait 1000us
state++; // count up the state
state++; // count up the state
}else if(state==1){
}else if(state==1){
SERVO_CHANNEL+=atomicServo[SERVO_1_ARR_POS]; // load the servo's value (0-1000us)
SERVO_CHANNEL+=atomicServo[SERVO_1_ARR_POS]; // load the servo's value (0-1000us)
state++; // count up the state
state++; // count up the state
#if defined(SERVO_2_HIGH)
#if defined(SERVO_2_HIGH)
SERVO_PULSE(SERVO_2_HIGH,2,SERVO_2_ARR_POS,SERVO_1_LOW); // the same here
SERVO_PULSE(SERVO_2_HIGH,2,SERVO_2_ARR_POS,SERVO_1_LOW); // the same here
#endif
#endif
#if defined(SERVO_3_HIGH)
#if defined(SERVO_3_HIGH)
SERVO_PULSE(SERVO_3_HIGH,4,SERVO_3_ARR_POS,SERVO_2_LOW);
SERVO_PULSE(SERVO_3_HIGH,4,SERVO_3_ARR_POS,SERVO_2_LOW);
#endif
#endif
#if defined(SERVO_4_HIGH)
#if defined(SERVO_4_HIGH)
SERVO_PULSE(SERVO_4_HIGH,6,SERVO_4_ARR_POS,SERVO_3_LOW);
SERVO_PULSE(SERVO_4_HIGH,6,SERVO_4_ARR_POS,SERVO_3_LOW);
#endif
#endif
#if defined(SERVO_5_HIGH)
#if defined(SERVO_5_HIGH)
SERVO_PULSE(SERVO_5_HIGH,8,SERVO_5_ARR_POS,SERVO_4_LOW);
SERVO_PULSE(SERVO_5_HIGH,8,SERVO_5_ARR_POS,SERVO_4_LOW);
#endif
#endif
#if defined(SERVO_6_HIGH)
#if defined(SERVO_6_HIGH)
SERVO_PULSE(SERVO_6_HIGH,10,SERVO_6_ARR_POS,SERVO_5_LOW);
SERVO_PULSE(SERVO_6_HIGH,10,SERVO_6_ARR_POS,SERVO_5_LOW);
#endif
#endif
#if defined(SERVO_7_HIGH)
#if defined(SERVO_7_HIGH)
SERVO_PULSE(SERVO_7_HIGH,12,SERVO_7_ARR_POS,SERVO_6_LOW);
SERVO_PULSE(SERVO_7_HIGH,12,SERVO_7_ARR_POS,SERVO_6_LOW);
#endif
#endif
#if defined(SERVO_8_HIGH)
#if defined(SERVO_8_HIGH)
SERVO_PULSE(SERVO_8_HIGH,14,SERVO_8_ARR_POS,SERVO_7_LOW);
SERVO_PULSE(SERVO_8_HIGH,14,SERVO_8_ARR_POS,SERVO_7_LOW);
#endif
#endif
}else{
}else{
LAST_LOW;
LAST_LOW;
#if defined(SERVO_RFR_300HZ)
#if defined(SERVO_RFR_300HZ)
#if defined(SERVO_3_HIGH) // if there are 3 or more servos we dont need to slow it down
#if defined(SERVO_3_HIGH) // if there are 3 or more servos we dont need to slow it down
SERVO_CHANNEL+=(SERVO_1K_US>>3); // 0 would be better but it causes bad jitter
SERVO_CHANNEL+=(SERVO_1K_US>>3); // 0 would be better but it causes bad jitter
state=0;
state=0;
#else // if there are less then 3 servos we need to slow it to not go over 300Hz (the highest working refresh rate for the digital servos for what i know..)
#else // if there are less then 3 servos we need to slow it to not go over 300Hz (the highest working refresh rate for the digital servos for what i know..)
SERVO_CHANNEL+=SERVO_1K_US;
SERVO_CHANNEL+=SERVO_1K_US;
if(state<4){
if(state<4){
state+=2;
state+=2;
}else{
}else{
state=0;
state=0;
}
}
#endif
#endif
#endif
#endif
#if defined(SERVO_RFR_160HZ)
#if defined(SERVO_RFR_160HZ)
#if defined(SERVO_4_HIGH) // if there are 4 or more servos we dont need to slow it down
#if defined(SERVO_4_HIGH) // if there are 4 or more servos we dont need to slow it down
SERVO_CHANNEL+=(SERVO_1K_US>>3); // 0 would be better but it causes bad jitter
SERVO_CHANNEL+=(SERVO_1K_US>>3); // 0 would be better but it causes bad jitter
state=0;
state=0;
#else // if there are less then 4 servos we need to slow it to not go over ~170Hz (the highest working refresh rate for analog servos)
#else // if there are less then 4 servos we need to slow it to not go over ~170Hz (the highest working refresh rate for analog servos)
SERVO_CHANNEL+=SERVO_1K_US;
SERVO_CHANNEL+=SERVO_1K_US;
if(state<8){
if(state<8){
state+=2;
state+=2;
}else{
}else{
state=0;
state=0;
}
}
#endif
#endif
#endif
#endif
#if defined(SERVO_RFR_50HZ) // to have ~ 50Hz for all servos
#if defined(SERVO_RFR_50HZ) // to have ~ 50Hz for all servos
SERVO_CHANNEL+=SERVO_1K_US;
SERVO_CHANNEL+=SERVO_1K_US;
if(state<30){
if(state<30){
state+=2;
state+=2;
}else{
}else{
state=0;
state=0;
}
}
#endif
#endif
}
}
}
}
#endif
#endif
/**************************************************************************************/
/**************************************************************************************/
/************ Motor software PWM generation ******************/
/************ Motor software PWM generation ******************/
/**************************************************************************************/
/**************************************************************************************/
// SW PWM is only used if there are not enough HW PWM pins (for exampe hexa on a promini)
// SW PWM is only used if there are not enough HW PWM pins (for exampe hexa on a promini)
#if (NUMBER_MOTOR > 4) && (defined(PROMINI) || defined(PROMICRO))
#if (NUMBER_MOTOR > 4) && (defined(PROMINI) || defined(PROMICRO))
/**************** Pre define the used ISR's and Timerchannels ******************/
/**************** Pre define the used ISR's and Timerchannels ******************/
#if !defined(PROMICRO)
#if !defined(PROMICRO)
#define SOFT_PWM_ISR1 TIMER0_COMPB_vect
#define SOFT_PWM_ISR1 TIMER0_COMPB_vect
#define SOFT_PWM_ISR2 TIMER0_COMPA_vect
#define SOFT_PWM_ISR2 TIMER0_COMPA_vect
#define SOFT_PWM_CHANNEL1 OCR0B
#define SOFT_PWM_CHANNEL1 OCR0B
#define SOFT_PWM_CHANNEL2 OCR0A
#define SOFT_PWM_CHANNEL2 OCR0A
#elif !defined(HWPWM6)
#elif !defined(HWPWM6)
#define SOFT_PWM_ISR1 TIMER3_COMPB_vect
#define SOFT_PWM_ISR1 TIMER3_COMPB_vect
#define SOFT_PWM_ISR2 TIMER3_COMPC_vect
#define SOFT_PWM_ISR2 TIMER3_COMPC_vect
#define SOFT_PWM_CHANNEL1 OCR3B
#define SOFT_PWM_CHANNEL1 OCR3B
#define SOFT_PWM_CHANNEL2 OCR3C
#define SOFT_PWM_CHANNEL2 OCR3C
#else
#else
#define SOFT_PWM_ISR2 TIMER0_COMPB_vect
#define SOFT_PWM_ISR2 TIMER0_COMPB_vect
#define SOFT_PWM_CHANNEL2 OCR0B
#define SOFT_PWM_CHANNEL2 OCR0B
#endif
#endif
/**************** Initialize Timers and PWM Channels ******************/
/**************** Initialize Timers and PWM Channels ******************/
void initializeSoftPWM() {
void initializeSoftPWM() {
#if !defined(PROMICRO)
#if !defined(PROMICRO)
TCCR0A = 0; // normal counting mode
TCCR0A = 0; // normal counting mode
#if (NUMBER_MOTOR > 4) && !defined(HWPWM6)
#if (NUMBER_MOTOR > 4) && !defined(HWPWM6)
TIMSK0 |= (1<<OCIE0B); // Enable CTC interrupt
TIMSK0 |= (1<<OCIE0B); // Enable CTC interrupt
#endif
#endif
#if (NUMBER_MOTOR > 6) || ((NUMBER_MOTOR == 6) && !defined(SERVO))
#if (NUMBER_MOTOR > 6) || ((NUMBER_MOTOR == 6) && !defined(SERVO))
TIMSK0 |= (1<<OCIE0A);
TIMSK0 |= (1<<OCIE0A);
#endif
#endif
#else
#else
#if !defined(HWPWM6)
#if !defined(HWPWM6)
TCCR3A &= ~(1<<WGM30) & ~(1<<WGM31); //normal counting & no prescaler
TCCR3A &= ~(1<<WGM30) & ~(1<<WGM31); //normal counting & no prescaler
TCCR3B &= ~(1<<WGM32) & ~(1<<CS31) & ~(1<<CS32) & ~(1<<WGM33);
TCCR3B &= ~(1<<WGM32) & ~(1<<CS31) & ~(1<<CS32) & ~(1<<WGM33);
TCCR3B |= (1<<CS30);
TCCR3B |= (1<<CS30);
TIMSK3 |= (1<<OCIE3B); // Enable CTC interrupt
TIMSK3 |= (1<<OCIE3B); // Enable CTC interrupt
#if (NUMBER_MOTOR > 6) || ((NUMBER_MOTOR == 6) && !defined(SERVO))
#if (NUMBER_MOTOR > 6) || ((NUMBER_MOTOR == 6) && !defined(SERVO))
TIMSK3 |= (1<<OCIE3C);
TIMSK3 |= (1<<OCIE3C);
#endif
#endif
#else
#else