diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 470ff7bec..c7a1ae721 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -98,13 +98,6 @@ bool isJackPlugged() #endif #if defined(PCBXLITES) -enum JackState -{ - SPEAKER_ACTIVE, - HEADPHONE_ACTIVE, - TRAINER_ACTIVE, -}; - uint8_t jackState = SPEAKER_ACTIVE; const char STR_JACK_HEADPHONE[] = "Headphone"; diff --git a/radio/src/pulses/ppm.cpp b/radio/src/pulses/ppm.cpp index 98099d340..9bf97ffec 100644 --- a/radio/src/pulses/ppm.cpp +++ b/radio/src/pulses/ppm.cpp @@ -53,6 +53,7 @@ void setupPulsesPPM(PpmPulsesData * ppmPulsesData, uint8_t channelsStart, int rest = limit(9000, rest, 65535); /* avoids that CCR2 is bigger than ARR which would cause reboot */ #if defined(STM32) *ppmPulsesData->ptr++ = rest; + *ppmPulsesData->ptr = 0; // it's needed in case PPM is sent without DMA (we stop when we reach this 0) #else *ptr = rest; *(ptr + 1) = 0; diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt index ea1057007..1ec29efd5 100644 --- a/radio/src/targets/taranis/CMakeLists.txt +++ b/radio/src/targets/taranis/CMakeLists.txt @@ -170,7 +170,7 @@ else() ) endif() -if(NOT PCB STREQUAL XLITE AND NOT PCB STREQUAL XLITES) +if(NOT PCB STREQUAL XLITE) set(TARGET_SRC ${TARGET_SRC} trainer_driver.cpp diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h index 5e2551c48..ae5c7bc5a 100644 --- a/radio/src/targets/taranis/board.h +++ b/radio/src/targets/taranis/board.h @@ -200,8 +200,17 @@ void extmoduleSendNextFrame(); #define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE) #if defined(PCBX9E) #define TRAINER_CONNECTED() (true) -#elif defined(PCBX7) +#elif defined(PCBX7) || defined(PCBX3) #define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_SET) +#elif defined(PCBXLITES) + enum JackState + { + SPEAKER_ACTIVE, + HEADPHONE_ACTIVE, + TRAINER_ACTIVE, + }; + extern uint8_t jackState; + #define TRAINER_CONNECTED() (jackState == TRAINER_ACTIVE) #elif defined(PCBXLITE) #define TRAINER_CONNECTED() false // there is no Trainer jack on Taranis X-Lite #else diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 1cece580b..08ddd6aa8 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -816,33 +816,42 @@ #endif // Trainer Port -#if defined(PCBXLITE) - #define TRAINER_RCC_AHB1Periph 0 - #define TRAINER_RCC_APB1Periph 0 -#elif defined(PCBX3) - #define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD) +#if defined(PCBXLITES) || defined(PCBX3) + // on these 2 radios the trainer port already uses DMA1_Stream6, we won't use the DMA + #define TRAINER_RCC_AHB1Periph RCC_AHB1Periph_GPIOD #define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM4 #define TRAINER_GPIO GPIOD #define TRAINER_IN_GPIO_PIN GPIO_Pin_13 // PD.13 #define TRAINER_IN_GPIO_PinSource GPIO_PinSource13 #define TRAINER_OUT_GPIO_PIN GPIO_Pin_12 // PD.12 #define TRAINER_OUT_GPIO_PinSource GPIO_PinSource12 +#if defined(PCBX3) #define TRAINER_DETECT_GPIO GPIOD #define TRAINER_DETECT_GPIO_PIN GPIO_Pin_11 // PD.11 +#endif #define TRAINER_TIMER TIM4 #define TRAINER_TIMER_IRQn TIM4_IRQn - #define TRAINER_GPIO_AF GPIO_AF_TIM4 - #define TRAINER_DMA DMA1 - #define TRAINER_DMA_CHANNEL DMA_Channel_5 - #define TRAINER_DMA_STREAM DMA1_Stream2 - #define TRAINER_DMA_IRQn DMA1_Stream2_IRQn - #define TRAINER_DMA_IRQHandler DMA1_Stream2_IRQHandler - #define TRAINER_DMA_FLAG_TC DMA_IT_TCIF2 + #define TRAINER_GPIO_AF GPIO_AF_TIM4 // TIM4_CH1 (Out) + TIM4_CH2 (In) #define TRAINER_TIMER_IRQn TIM4_IRQn #define TRAINER_TIMER_IRQHandler TIM4_IRQHandler #define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) + #define TRAINER_OUT_CCMR1 TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE; + #define TRAINER_IN_CCMR1 TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_CC2S_0; + #define TRAINER_OUT_COUNTER_REGISTER TRAINER_TIMER->CCR1 + #define TRAINER_IN_COUNTER_REGISTER TRAINER_TIMER->CCR2 + #define TRAINER_SETUP_REGISTER TRAINER_TIMER->CCR3 + #define TRAINER_OUT_INTERRUPT_FLAG TIM_SR_CC3IF + #define TRAINER_OUT_INTERRUPT_ENABLE TIM_DIER_CC3IE + #define TRAINER_IN_INTERRUPT_ENABLE TIM_DIER_CC2IE + #define TRAINER_IN_INTERRUPT_FLAG TIM_SR_CC2IF + #define TRAINER_OUT_CCER TIM_CCER_CC1E + #define TRAINER_CCER_POLARYTY TIM_CCER_CC1P + #define TRAINER_IN_CCER TIM_CCER_CC2E +#elif defined(PCBXLITE) + #define TRAINER_RCC_AHB1Periph 0 + #define TRAINER_RCC_APB1Periph 0 #else - #define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC) + #define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA1) #define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM3 #define TRAINER_GPIO GPIOC #define TRAINER_IN_GPIO_PIN GPIO_Pin_8 // PC.08 @@ -863,6 +872,18 @@ #define TRAINER_TIMER_IRQn TIM3_IRQn #define TRAINER_TIMER_IRQHandler TIM3_IRQHandler #define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) + #define TRAINER_OUT_CCMR2 TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE; + #define TRAINER_IN_CCMR2 TIM_CCMR2_IC3F_0 | TIM_CCMR2_IC3F_1 | TIM_CCMR2_CC3S_0; + #define TRAINER_OUT_COUNTER_REGISTER TRAINER_TIMER->CCR4 + #define TRAINER_IN_COUNTER_REGISTER TRAINER_TIMER->CCR3 + #define TRAINER_SETUP_REGISTER TRAINER_TIMER->CCR1 + #define TRAINER_OUT_INTERRUPT_FLAG TIM_SR_CC1IF + #define TRAINER_OUT_INTERRUPT_ENABLE TIM_DIER_CC1IE + #define TRAINER_IN_INTERRUPT_ENABLE TIM_DIER_CC3IE + #define TRAINER_IN_INTERRUPT_FLAG TIM_SR_CC3IF + #define TRAINER_OUT_CCER TIM_CCER_CC4E + #define TRAINER_IN_CCER TIM_CCER_CC3E + #define TRAINER_CCER_POLARYTY TIM_CCER_CC4P #endif // Serial Port @@ -1181,7 +1202,7 @@ #define SD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1) #define SD_RCC_APB1Periph RCC_APB1Periph_SPI2 #define SD_GPIO_PRESENT_GPIO GPIOD -#if defined(PCBXLITE) +#if defined(PCBXLITE) || defined(PCBX3) #define SD_GPIO_PRESENT_GPIO_PIN GPIO_Pin_10 // PD.10 #else #define SD_GPIO_PRESENT_GPIO_PIN GPIO_Pin_9 // PD.09 @@ -1226,8 +1247,8 @@ #define JACK_DETECT_GPIO_PIN GPIO_Pin_13 // PC.13 #define AUDIO_SPEAKER_ENABLE_GPIO GPIOD #define AUDIO_SPEAKER_ENABLE_GPIO_PIN GPIO_Pin_14 // PD.14 - #define HEADPHONE_TRAINER_SWITCH_GPIO GPIOD - #define HEADPHONE_TRAINER_SWITCH_GPIO_PIN GPIO_Pin_13 // PD.13 + #define HEADPHONE_TRAINER_SWITCH_GPIO GPIOD + #define HEADPHONE_TRAINER_SWITCH_GPIO_PIN GPIO_Pin_9 // PD.09 #else #define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1) #endif diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp index 67eb441cb..000c0721b 100644 --- a/radio/src/targets/taranis/trainer_driver.cpp +++ b/radio/src/targets/taranis/trainer_driver.cpp @@ -20,7 +20,9 @@ #include "opentx.h" +#if defined(HEARTBEAT_USART) DMAFifo<32> heartbeatFifo __DMA (HEARTBEAT_DMA_Stream); +#endif void trainerSendNextFrame(); @@ -39,7 +41,11 @@ void init_trainer_ppm() TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS TRAINER_TIMER->ARR = 45000; - TRAINER_TIMER->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE; // PWM mode 1 +#if defined(TRAINER_OUT_CCMR1) + TRAINER_TIMER->CCMR1 = TRAINER_OUT_CCMR1; +#elif defined(TRAINER_OUT_CCMR2) + TRAINER_TIMER->CCMR2 = TRAINER_OUT_CCMR2; +#endif TRAINER_TIMER->BDTR = TIM_BDTR_MOE; TRAINER_TIMER->EGR = 1; TRAINER_TIMER->DIER |= TIM_DIER_UDE; @@ -48,18 +54,23 @@ void init_trainer_ppm() setupPulsesPPMTrainer(); trainerSendNextFrame(); +#if defined(TRAINER_DMA_STREAM) NVIC_EnableIRQ(TRAINER_DMA_IRQn); NVIC_SetPriority(TRAINER_DMA_IRQn, 7); +#endif + NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); } void stop_trainer_ppm() { +#if defined(TRAINER_DMA_STREAM) NVIC_DisableIRQ(TRAINER_DMA_IRQn); - NVIC_DisableIRQ(TRAINER_TIMER_IRQn); - TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA +#endif + + NVIC_DisableIRQ(TRAINER_TIMER_IRQn); TRAINER_TIMER->DIER = 0; TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter } @@ -79,10 +90,14 @@ void init_trainer_capture() TRAINER_TIMER->ARR = 0xFFFF; TRAINER_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5uS TRAINER_TIMER->CR2 = 0; - TRAINER_TIMER->CCMR2 = TIM_CCMR2_IC3F_0 | TIM_CCMR2_IC3F_1 | TIM_CCMR2_CC3S_0; - TRAINER_TIMER->CCER = TIM_CCER_CC3E; +#if defined(TRAINER_IN_CCMR1) + TRAINER_TIMER->CCMR1 = TRAINER_IN_CCMR1; +#elif defined(TRAINER_IN_CCMR2) + TRAINER_TIMER->CCMR2 = TRAINER_IN_CCMR2; +#endif + TRAINER_TIMER->CCER = TRAINER_IN_CCER; TRAINER_TIMER->SR &= ~TIM_SR_CC3IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags - TRAINER_TIMER->DIER |= TIM_DIER_CC3IE; + TRAINER_TIMER->DIER |= TRAINER_IN_INTERRUPT_ENABLE; TRAINER_TIMER->CR1 = TIM_CR1_CEN; NVIC_EnableIRQ(TRAINER_TIMER_IRQn); @@ -98,18 +113,26 @@ void stop_trainer_capture() void trainerSendNextFrame() { - TRAINER_TIMER->CCR4 = GET_TRAINER_PPM_DELAY() * 2; - TRAINER_TIMER->CCER = TIM_CCER_CC4E | (GET_TRAINER_PPM_POLARITY() ? 0 : TIM_CCER_CC4P); - TRAINER_TIMER->CCR1 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance + TRAINER_OUT_COUNTER_REGISTER = GET_TRAINER_PPM_DELAY() * 2; + TRAINER_TIMER->CCER = TRAINER_OUT_CCER | (GET_TRAINER_PPM_POLARITY() ? 0 : TRAINER_CCER_POLARYTY); + TRAINER_SETUP_REGISTER = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance +#if defined(TRAINER_DMA_STREAM) TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA TRAINER_DMA_STREAM->CR |= TRAINER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; TRAINER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&TRAINER_TIMER->ARR); TRAINER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(trainerPulsesData.ppm.pulses); TRAINER_DMA_STREAM->NDTR = trainerPulsesData.ppm.ptr - trainerPulsesData.ppm.pulses; TRAINER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA +#else + 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 +#endif } +#if defined(TRAINER_DMA_STREAM) extern "C" void TRAINER_DMA_IRQHandler() { if (!DMA_GetITStatus(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC)) @@ -117,9 +140,10 @@ extern "C" void TRAINER_DMA_IRQHandler() DMA_ClearITPendingBit(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC); - TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag - TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt + TRAINER_TIMER->SR &= ~TRAINER_OUT_INTERRUPT_FLAG; // Clear flag + TRAINER_TIMER->DIER |= TRAINER_OUT_INTERRUPT_ENABLE; // Enable this interrupt } +#endif extern "C" void TRAINER_TIMER_IRQHandler() { @@ -129,14 +153,15 @@ extern "C" void TRAINER_TIMER_IRQHandler() bool doCapture = false; // What mode? in or out? - if ((TRAINER_TIMER->DIER & TIM_DIER_CC3IE) && (TRAINER_TIMER->SR & TIM_SR_CC3IF)) { + if ((TRAINER_TIMER->DIER & TRAINER_IN_INTERRUPT_ENABLE) && (TRAINER_TIMER->SR & TRAINER_IN_INTERRUPT_FLAG)) { // capture mode on trainer jack - capture = TRAINER_TIMER->CCR3; + capture = TRAINER_IN_COUNTER_REGISTER; if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK) { doCapture = true; } } +#if defined(TRAINER_MODULE_HEARTBEAT) if ((TRAINER_TIMER->DIER & TIM_DIER_CC2IE) && (TRAINER_TIMER->SR & TIM_SR_CC2IF)) { // capture mode on heartbeat pin (external module) capture = TRAINER_TIMER->CCR2; @@ -144,22 +169,36 @@ extern "C" void TRAINER_TIMER_IRQHandler() doCapture = true; } } +#endif if (doCapture) { captureTrainerPulses(capture); } // PPM out compare interrupt - if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) { + if ((TRAINER_TIMER->DIER & TRAINER_OUT_INTERRUPT_ENABLE) && (TRAINER_TIMER->SR & TRAINER_OUT_INTERRUPT_FLAG)) { // compare interrupt - TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt - TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag + TRAINER_TIMER->DIER &= ~TRAINER_OUT_INTERRUPT_ENABLE; // stop this interrupt + TRAINER_TIMER->SR &= ~TRAINER_OUT_INTERRUPT_FLAG; // Clear flag setupPulsesPPMTrainer(); trainerSendNextFrame(); } + +#if !defined(TRAINER_DMA_STREAM) + // 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 &= ~TRAINER_OUT_INTERRUPT_FLAG; // Clear this flag + TRAINER_TIMER->DIER |= TRAINER_OUT_INTERRUPT_ENABLE; // Enable this interrupt + } + } +#endif } -void init_cppm_on_heartbeat_capture(void) +#if defined(TRAINER_MODULE_HEARTBEAT) +void init_cppm_on_heartbeat_capture() { EXTERNAL_MODULE_ON(); @@ -196,7 +235,9 @@ void stop_cppm_on_heartbeat_capture() EXTERNAL_MODULE_OFF(); } } +#endif +#if defined(HEARTBEAT_USART) void init_sbus_on_heartbeat_capture() { EXTERNAL_MODULE_ON(); @@ -258,13 +299,16 @@ void stop_sbus_on_heartbeat_capture() EXTERNAL_MODULE_OFF(); } } +#endif int sbusGetByte(uint8_t * byte) { switch (currentTrainerMode) { +#if defined(HEARTBEAT_USART) case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE: return heartbeatFifo.pop(*byte); -#if !defined(PCBX7) && !defined(PCBX9E) && !defined(PCBX3) +#endif +#if !defined(PCBX7) && !defined(PCBX9E) && !defined(PCBX3) && !defined(PCBXLITE) case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT: return serial2RxFifo.pop(*byte); #endif