// PPM output // Timer 1, channel 1 on PA8 for prototype // Pin is AF1 function for timer 1 static void extmodulePpmStart() { EXTERNAL_MODULE_ON(); // Timer1 configure_pins(EXTMODULE_GPIO_PIN, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_3 | PIN_OS25); EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN ; // setupPulsesPPM() is also configuring registers, // so it has to be called after the peripheral is enabled setupPulsesPPM(EXTERNAL_MODULE) ; EXTMODULE_TIMER->ARR = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++ ; EXTMODULE_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE ; // PWM mode 1 EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE ; EXTMODULE_TIMER->EGR = 1 ; EXTMODULE_TIMER->DIER = TIM_DIER_UDE ; EXTMODULE_TIMER->SR &= ~TIM_SR_UIF ; // Clear flag EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF ; // Clear flag EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE ; EXTMODULE_TIMER->DIER |= TIM_DIER_UIE ; EXTMODULE_TIMER->CR1 = TIM_CR1_CEN ; NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn) ; NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7); NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn) ; NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 7); }
void init_main_ppm(uint32_t period, uint32_t out_enable) { register Pwm *pwmptr ; setupPulsesPPM(EXTERNAL_MODULE) ; if (out_enable) { module_output_active(); } pwmptr = PWM ; // PWM3 for PPM output pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B ; // CLKA if (!g_model.moduleData[EXTERNAL_MODULE].ppmPulsePol) { pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200 ; // CPOL } pwmptr->PWM_CH_NUM[3].PWM_CPDR = period ; // Period in half uS pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period ; // Period in half uS pwmptr->PWM_CH_NUM[3].PWM_CDTY = g_model.moduleData[EXTERNAL_MODULE].ppmDelay*100+600; // Duty in half uS pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = g_model.moduleData[EXTERNAL_MODULE].ppmDelay*100+600; // Duty in half uS pwmptr->PWM_ENA = PWM_ENA_CHID3 ; // Enable channel 3 pwmptr->PWM_IER1 = PWM_IER1_CHID3 ; NVIC_SetPriority(PWM_IRQn, 3 ) ; NVIC_EnableIRQ(PWM_IRQn) ; }
void init_main_ppm( uint32_t period, uint32_t out_enable ) { register Pwm *pwmptr ; perOut(g_chans512, 0) ; setupPulsesPPM() ; if ( out_enable ) { module_output_active() ; } pwmptr = PWM ; // PWM3 for PPM output pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B ; // CLKA if (g_model.pulsePol == 0) { pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200 ; // CPOL } pwmptr->PWM_CH_NUM[3].PWM_CPDR = period ; // Period in half uS pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period ; // Period in half uS pwmptr->PWM_CH_NUM[3].PWM_CDTY = g_model.ppmDelay*100+600 ; // Duty in half uS pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = g_model.ppmDelay*100+600 ; // Duty in half uS pwmptr->PWM_ENA = PWM_ENA_CHID3 ; // Enable channel 3 pwmptr->PWM_IER1 = PWM_IER1_CHID3 ; #ifdef REVB configure_pins( PIO_PC15, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP ) ; #endif #ifdef REVB // PWM1 for PPM2 pwmptr->PWM_CH_NUM[1].PWM_CMR = 0x0000000B ; // CLKB if (g_model.pulsePol == 0) { pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200 ; // CPOL } pwmptr->PWM_CH_NUM[1].PWM_CPDR = period ; // Period pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = period ; // Period pwmptr->PWM_CH_NUM[1].PWM_CDTY = g_model.ppmDelay*100+600 ; // Duty pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = g_model.ppmDelay*100+600 ; // Duty pwmptr->PWM_ENA = PWM_ENA_CHID1 ; // Enable channel 1 #endif pwmptr->PWM_IER1 = PWM_IER1_CHID1 ; NVIC_SetPriority(PWM_IRQn, 3 ) ; NVIC_EnableIRQ(PWM_IRQn) ; }
// PPM output // Timer 1, channel 1 on PA8 for prototype // Pin is AF1 function for timer 1 static void init_pa7_ppm() { EXTERNAL_RF_ON(); // Timer1 setupPulsesPPM(EXTERNAL_MODULE) ; ppmStreamPtr[EXTERNAL_MODULE] = ppmStream[EXTERNAL_MODULE]; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock #if defined(REV3) configure_pins( 0x0100, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; #else configure_pins( PIN_EXTPPM_OUT, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_3 | PIN_OS25 | PIN_PUSHPULL ) ; #endif RCC->APB2ENR |= RCC_APB2ENR_TIM8EN ; // Enable clock TIM8->CR1 &= ~TIM_CR1_CEN ; TIM8->ARR = *ppmStreamPtr[EXTERNAL_MODULE]++ ; TIM8->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz #if defined(REV3) TIM8->CCER = TIM_CCER_CC1E ; #else TIM8->CCER = TIM_CCER_CC1NE; if(!g_model.moduleData[EXTERNAL_MODULE].ppmPulsePol) TIM8->CCER |= TIM_CCER_CC1NP; #endif TIM8->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE ; // PWM mode 1 TIM8->CCR1 = (g_model.moduleData[EXTERNAL_MODULE].ppmDelay*50+300)*2; TIM8->BDTR = TIM_BDTR_MOE ; TIM8->EGR = 1 ; TIM8->DIER = TIM_DIER_UDE ; TIM8->SR &= ~TIM_SR_UIF ; // Clear flag TIM8->SR &= ~TIM_SR_CC2IF ; // Clear flag TIM8->DIER |= TIM_DIER_CC2IE ; TIM8->DIER |= TIM_DIER_UIE ; TIM8->CR1 = TIM_CR1_CEN ; NVIC_EnableIRQ(TIM8_CC_IRQn) ; NVIC_SetPriority(TIM8_CC_IRQn, 7); NVIC_EnableIRQ(TIM8_UP_TIM13_IRQn) ; NVIC_SetPriority(TIM8_UP_TIM13_IRQn, 7); }
void init_main_ppm(uint32_t period, uint32_t out_enable) { register Pwm *pwmptr ; setupPulsesPPM(EXTERNAL_MODULE) ; if (out_enable) { module_output_active(); } pwmptr = PWM ; // PWM3 for PPM output pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B ; // CLKA if (!g_model.moduleData[EXTERNAL_MODULE].ppmPulsePol) { pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200 ; // CPOL } pwmptr->PWM_CH_NUM[3].PWM_CPDR = period ; // Period in half uS pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period ; // Period in half uS pwmptr->PWM_CH_NUM[3].PWM_CDTY = g_model.moduleData[EXTERNAL_MODULE].ppmDelay*100+600; // Duty in half uS pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = g_model.moduleData[EXTERNAL_MODULE].ppmDelay*100+600; // Duty in half uS pwmptr->PWM_ENA = PWM_ENA_CHID3 ; // Enable channel 3 pwmptr->PWM_IER1 = PWM_IER1_CHID3 ; #if !defined(REVA) // PWM1 for PPM2 configure_pins(PIO_PC15, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP ) ; pwmptr->PWM_CH_NUM[1].PWM_CMR = 0x0000000B ; // CLKB if (!g_model.moduleData[EXTRA_MODULE].ppmPulsePol) { pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200 ; // CPOL } pwmptr->PWM_CH_NUM[1].PWM_CPDR = period ; // Period pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = period ; // Period pwmptr->PWM_CH_NUM[1].PWM_CDTY = g_model.moduleData[EXTRA_MODULE].ppmDelay*100+600 ; // Duty pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = g_model.moduleData[EXTRA_MODULE].ppmDelay*100+600 ; // Duty pwmptr->PWM_ENA = PWM_ENA_CHID1 ; // Enable channel 1 pwmptr->PWM_IER1 = PWM_IER1_CHID1 ; #endif NVIC_SetPriority(PWM_IRQn, 3 ) ; NVIC_EnableIRQ(PWM_IRQn) ; }
// PPM output // Timer 1, channel 1 on PA8 for prototype // Pin is AF1 function for timer 1 static void init_pa10_ppm() { INTERNAL_RF_ON(); // Timer1 setupPulsesPPM(INTERNAL_MODULE) ; ppmStreamPtr[INTERNAL_MODULE] = ppmStream[INTERNAL_MODULE]; //RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN ; // Enable portA clock RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIO_INTPPM, ENABLE); configure_pins( PIN_INTPPM_OUT, PIN_PERIPHERAL | PIN_PORTA | PIN_PER_1 | PIN_OS25 | PIN_PUSHPULL ) ; RCC->APB2ENR |= RCC_APB2ENR_TIM1EN ; // Enable clock TIM1->CR1 &= ~TIM_CR1_CEN ; TIM1->ARR = *ppmStreamPtr[INTERNAL_MODULE]++ ; TIM1->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 2000000 - 1 ; // 0.5uS from 30MHz TIM1->CCER = TIM_CCER_CC3E ; TIM1->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 ; // PWM mode 1 TIM1->CCMR1 = TIM_CCMR1_OC2PE ; // PWM mode 1 TIM1->CCR3 = (g_model.moduleData[INTERNAL_MODULE].ppmDelay*50+300)*2; TIM1->BDTR = TIM_BDTR_MOE ; TIM1->EGR = 1 ; TIM1->DIER = TIM_DIER_UDE ; TIM1->SR &= ~TIM_SR_UIF ; // Clear flag TIM1->SR &= ~TIM_SR_CC2IF ; // Clear flag TIM1->DIER |= TIM_DIER_CC2IE ; TIM1->DIER |= TIM_DIER_UIE ; TIM1->CR1 = TIM_CR1_CEN ; NVIC_EnableIRQ(TIM1_CC_IRQn) ; NVIC_SetPriority(TIM1_CC_IRQn, 7); NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn) ; NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 7); }
extern "C" void PWM_IRQHandler(void) { register Pwm *pwmptr; register Ssc *sscptr; uint32_t period; uint32_t reason; pwmptr = PWM; reason = pwmptr->PWM_ISR1 ; if (reason & PWM_ISR1_CHID3) { // Use the current protocol, don't switch until set_up_pulses switch (s_current_protocol[EXTERNAL_MODULE]) { case PROTO_PXX: // Alternate periods of 6.5mS and 2.5 mS period = pwmptr->PWM_CH_NUM[3].PWM_CPDR; if (period == 2500 * 2) { period = 6500 * 2; } else { period = 2500 * 2; } pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS if (period != 2500 * 2) { setupPulses(EXTERNAL_MODULE); } else { // Kick off serial output here sscptr = SSC; sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.pulses); sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].pxx.pulses; sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers } break; case PROTO_DSM2_LP45: case PROTO_DSM2_DSM2: case PROTO_DSM2_DSMX: // Alternate periods of 19.5mS and 2.5 mS period = pwmptr->PWM_CH_NUM[3].PWM_CPDR; if (period == 2500 * 2) { period = 19500 * 2; } else { period = 2500 * 2; } pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS if (period != 2500 * 2) { setupPulses(EXTERNAL_MODULE); } else { // Kick off serial output here sscptr = SSC; sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses); sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.pulses; sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers } break; default: pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = modulePulsesData[EXTERNAL_MODULE].ppm.pulses[modulePulsesData[EXTERNAL_MODULE].ppm.index++]; // Period in half uS if (modulePulsesData[EXTERNAL_MODULE].ppm.pulses[modulePulsesData[EXTERNAL_MODULE].ppm.index] == 0) { modulePulsesData[EXTERNAL_MODULE].ppm.index = 0; setupPulses(EXTERNAL_MODULE); } break; } } #if !defined(REVA) if (reason & PWM_ISR1_CHID1) { pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = modulePulsesData[EXTRA_MODULE].ppm.pulses[modulePulsesData[EXTRA_MODULE].ppm.index++] ; // Period in half uS if (modulePulsesData[EXTRA_MODULE].ppm.pulses[modulePulsesData[EXTRA_MODULE].ppm.index] == 0) { modulePulsesData[EXTRA_MODULE].ppm.index = 0; setupPulsesPPM(EXTRA_MODULE); } } #endif }
extern "C" void PWM_IRQHandler(void) { register Pwm *pwmptr; register Ssc *sscptr; uint32_t period; uint32_t reason; pwmptr = PWM; reason = pwmptr->PWM_ISR1 ; if (reason & PWM_ISR1_CHID3) { // Use the current protocol, don't switch until set_up_pulses switch (s_current_protocol[EXTERNAL_MODULE]) { case PROTO_PXX: // Alternate periods of 15.5mS and 2.5 mS period = pwmptr->PWM_CH_NUM[3].PWM_CPDR; if (period == 5000) { // 2.5 mS period = 15500 * 2; } else { period = 5000; } pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS if (period != 5000) { // 2.5 mS setupPulses(EXTERNAL_MODULE); } else { // Kick off serial output here sscptr = SSC; sscptr->SSC_TPR = CONVERT_PTR_UINT(pxxStream[EXTERNAL_MODULE]); sscptr->SSC_TCR = (uint8_t *)pxxStreamPtr[EXTERNAL_MODULE] - (uint8_t *)pxxStream[EXTERNAL_MODULE]; sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers } break; case PROTO_DSM2_LP45: case PROTO_DSM2_DSM2: case PROTO_DSM2_DSMX: // Alternate periods of 19.5mS and 2.5 mS period = pwmptr->PWM_CH_NUM[3].PWM_CPDR; if (period == 5000) { // 2.5 mS period = 19500 * 2; } else { period = 5000; } pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS if (period != 5000) { // 2.5 mS setupPulses(0); } else { // Kick off serial output here sscptr = SSC; sscptr->SSC_TPR = CONVERT_PTR_UINT(dsm2Stream); sscptr->SSC_TCR = (uint8_t *)dsm2StreamPtr - (uint8_t *)dsm2Stream; sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers } break; default: pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = ppmStream[EXTERNAL_MODULE][ppmStreamIndex[EXTERNAL_MODULE]++]; // Period in half uS if (ppmStream[EXTERNAL_MODULE][ppmStreamIndex[EXTERNAL_MODULE]] == 0) { ppmStreamIndex[EXTERNAL_MODULE] = 0; setupPulses(EXTERNAL_MODULE); } break; } } if (reason & PWM_ISR1_CHID1) { pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = ppmStream[EXTRA_MODULE][ppmStreamIndex[EXTRA_MODULE]++] ; // Period in half uS if (ppmStream[EXTRA_MODULE][ppmStreamIndex[EXTRA_MODULE]] == 0) { ppmStreamIndex[EXTRA_MODULE] = 0; setupPulsesPPM(EXTRA_MODULE); } } }
void setupPulses() { uint8_t required_protocol ; required_protocol = g_model.protocol ; // Sort required_protocol depending on student mode and PPMSIM allowed if ( g_eeGeneral.enablePpmsim ) { if ( SlaveMode ) { required_protocol = PROTO_PPMSIM ; } } if ( PausePulses ) { required_protocol = PROTO_NONE ; } // SPY_ON; if ( Current_protocol != required_protocol ) { Current_protocol = required_protocol ; // switch mode here TCCR1B = 0 ; // Stop counter TCNT1 = 0 ; #ifdef CPUM2561 TIMSK1 &= ~( (1<<OCIE1A) | (1<<OCIE1B) | (1<<OCIE1C) | (1<<ICIE1) | (1<<TOIE1) ) ; // All interrupts off // TIMSK1 &= ~(1<<OCIE1C) ; // COMPC1 off TIFR1 = ( (1<<OCF1A) | (1<<OCF1B) | (1<<OCF1C) | (1<<ICF1) | (1<<TOV1) ) ; // Clear all pending interrupts TIFR3 = ( (1<<OCF3A) | (1<<OCF3B) | (1<<OCF3C) | (1<<ICF3) | (1<<TOV3) ) ; // Clear all pending interrupts #else TIMSK &= ~0x3C ; // All interrupts off ETIMSK &= ~(1<<OCIE1C) ; // COMPC1 off TIFR = 0x3C ; // Clear all pending interrupts ETIFR = 0x3F ; // Clear all pending interrupts #endif switch(required_protocol) { case PROTO_PPM: set_timer3_capture() ; setPpmTimers() ; break; case PROTO_PXX: set_timer3_capture() ; OCR1B = 7000 ; // Next frame starts in 3.5 mS OCR1C = 4000 ; // Next frame setup in 2 mS #ifdef CPUM2561 TIMSK1 |= (1<<OCIE1B) | (1<<OCIE1C); // Enable COMPB and COMPC #else TIMSK |= (1<<OCIE1B) ; // Enable COMPB ETIMSK |= (1<<OCIE1C); // Enable COMPC #endif TCCR1A = 0; TCCR1B = (2<<CS10); //ICNC3 16MHz / 8 break; #ifdef MULTI_PROTOCOL case PROTO_MULTI: #endif // MULTI_PROTOCOL #ifdef SBUS_PROTOCOL case PROTO_SBUS: #endif // SBUS_PROTOCOL case PROTO_DSM2: set_timer3_capture() ; OCR1C = 200 ; // 100 uS TCNT1 = 300 ; // Past the OCR1C value ICR1 = 44000 ; // Next frame starts in 11/22 mS #ifdef CPUM2561 TIMSK1 |= (1<<ICIE1) ; // Enable CAPT #else TIMSK |= (1<<TICIE1) ; // Enable CAPT #endif #ifdef CPUM2561 TIMSK1 |= (1<<OCIE1C); // Enable COMPC #else ETIMSK |= (1<<OCIE1C); // Enable COMPC #endif TCCR1A = (0<<WGM10) ; TCCR1B = (3 << WGM12) | (2<<CS10) ; // CTC ICR, 16MHz / 8 break; case PROTO_PPM16 : case PROTO_PPMSIM : if ( required_protocol == PROTO_PPMSIM ) { setupPulsesPPM(PROTO_PPMSIM); PORTB &= ~(1<<OUT_B_PPM); // Hold PPM output low } else { setPpmTimers() ; setupPulsesPPM(PROTO_PPM16); } OCR3A = 50000 ; OCR3B = 5000 ; set_timer3_ppm() ; break ; // case PROTO_PPMSIM : // setupPulsesPPM(PROTO_PPMSIM); // PORTB &= ~(1<<OUT_B_PPM); // Hold PPM output low // OCR3A = 50000 ; // OCR3B = 5000 ; // set_timer3_ppm() ; // break ; } } switch(required_protocol) { case PROTO_PPM: setupPulsesPPM( PROTO_PPM ); // Don't enable interrupts through here break; case PROTO_PXX: sei() ; // Interrupts allowed here setupPulsesPXX(); break; #ifdef MULTI_PROTOCOL case PROTO_MULTI: #endif // MULTI_PROTOCOL #ifdef SBUS_PROTOCOL case PROTO_SBUS: #endif // SBUS_PROTOCOL case PROTO_DSM2: sei() ; // Interrupts allowed here setupPulsesSerial(); break; case PROTO_PPM16 : setupPulsesPPM( PROTO_PPM ); // Don't enable interrupts through here // PPM16 pulses are set up automatically within the interrupts break ; } // SPY_OFF; //extern void nothing() ; // nothing() ; asm("") ; }