// Trainer PPM oputput PC9, Timer 3 channel 4, (Alternate Function 2) void init_trainer_ppm() { trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses; configure_pins( TRAINER_GPIO_PIN_OUT, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_2 | PIN_OS25) ; configure_pins( TRAINER_GPIO_PIN_IN, PIN_PORTA | PIN_INPUT ) ; TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN ; // setupTrainerPulses() is also configuring registers, // so it has to be called after the peripheral is enabled setupTrainerPulses() ; TRAINER_TIMER->ARR = *trainerPulsesData.ppm.ptr++ ; TRAINER_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1 ; // 0.5uS TRAINER_TIMER->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE ; // PWM mode 1 TRAINER_TIMER->BDTR = TIM_BDTR_MOE ; TRAINER_TIMER->EGR = 1 ; TRAINER_TIMER->SR &= ~TIM_SR_UIF ; // Clear flag TRAINER_TIMER->SR &= ~TIM_SR_CC1IF ; // Clear flag TRAINER_TIMER->DIER |= TIM_DIER_CC1IE ; TRAINER_TIMER->DIER |= TIM_DIER_UIE ; TRAINER_TIMER->CR1 = TIM_CR1_CEN ; NVIC_EnableIRQ(TRAINER_TIMER_IRQn) ; NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); }
extern "C" void TIM3_IRQHandler() { uint16_t capture = 0; bool doCapture = false ; // What mode? in or out? if ( (TRAINER_TIMER->DIER & TIM_DIER_CC3IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC3IF ) ) { // capture mode on trainer jack capture = TRAINER_TIMER->CCR3 ; if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK) doCapture = true; } if ( ( TRAINER_TIMER->DIER & TIM_DIER_CC2IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC2IF ) ) { // capture mode on heartbeat pin (external module) capture = TRAINER_TIMER->CCR2 ; if (currentTrainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE) doCapture = true ; } if (doCapture) { captureTrainerPulses(capture); } // PPM out compare interrupt if ( ( TRAINER_TIMER->DIER & TIM_DIER_CC1IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC1IF ) ) { // compare interrupt TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE ; // stop this interrupt TRAINER_TIMER->SR &= ~TIM_SR_CC1IF ; // Clear flag setupTrainerPulses() ; trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses; TRAINER_TIMER->DIER |= TIM_DIER_UDE ; TRAINER_TIMER->SR &= ~TIM_SR_UIF ; // Clear this flag TRAINER_TIMER->DIER |= TIM_DIER_UIE ; // Enable this interrupt } // PPM out update interrupt if ( (TRAINER_TIMER->DIER & TIM_DIER_UIE) && ( TRAINER_TIMER->SR & TIM_SR_UIF ) ) { TRAINER_TIMER->SR &= ~TIM_SR_UIF ; // Clear flag TRAINER_TIMER->ARR = *trainerPulsesData.ppm.ptr++ ; if ( *trainerPulsesData.ppm.ptr == 0 ) { TRAINER_TIMER->SR &= ~TIM_SR_CC1IF ; // Clear this flag TRAINER_TIMER->DIER |= TIM_DIER_CC1IE ; // Enable this interrupt } } }
extern "C" void TIM3_IRQHandler() { uint16_t capture = 0; static uint16_t lastCapt ; uint16_t val ; bool doCapture = false ; // What mode? in or out? if ( (TRAINER_TIMER->DIER & TIM_DIER_CC3IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC3IF ) ) { // capture mode on trainer jack capture = TRAINER_TIMER->CCR3 ; doCapture = true; } if ( ( TRAINER_TIMER->DIER & TIM_DIER_CC2IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC2IF ) ) { // capture mode on heartbeat pin (external module) capture = TRAINER_TIMER->CCR2 ; doCapture = true ; } if (doCapture) { val = (uint16_t)(capture - lastCapt) / 2 ; lastCapt = capture; // We process g_ppmInsright here to make servo movement as smooth as possible // while under trainee control if (val>4000 && val<19000) { // G: Prioritize reset pulse. (Needed when less than 16 incoming pulses) ppmInState = 1; // triggered } else { if (ppmInState>0 && ppmInState<=16) { if (val>800 && val<2200) { ppmInValid = PPM_IN_VALID_TIMEOUT; g_ppmIns[ppmInState++ - 1] = (int16_t)(val - 1500)*(g_eeGeneral.PPM_Multiplier+10)/10; //+-500 != 512, but close enough. } else { ppmInState = 0; // not triggered } } } } // PPM out compare interrupt if ( ( TRAINER_TIMER->DIER & TIM_DIER_CC1IE ) && ( TRAINER_TIMER->SR & TIM_SR_CC1IF ) ) { // compare interrupt TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE ; // stop this interrupt TRAINER_TIMER->SR &= ~TIM_SR_CC1IF ; // Clear flag setupTrainerPulses() ; trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses; TRAINER_TIMER->DIER |= TIM_DIER_UDE ; TRAINER_TIMER->SR &= ~TIM_SR_UIF ; // Clear this flag TRAINER_TIMER->DIER |= TIM_DIER_UIE ; // Enable this interrupt } // PPM out update interrupt if ( (TRAINER_TIMER->DIER & TIM_DIER_UIE) && ( TRAINER_TIMER->SR & TIM_SR_UIF ) ) { TRAINER_TIMER->SR &= ~TIM_SR_UIF ; // Clear flag TRAINER_TIMER->ARR = *trainerPulsesData.ppm.ptr++ ; if ( *trainerPulsesData.ppm.ptr == 0 ) { TRAINER_TIMER->SR &= ~TIM_SR_CC1IF ; // Clear this flag TRAINER_TIMER->DIER |= TIM_DIER_CC1IE ; // Enable this interrupt } } }