From 404c5a85538a4cc394e6412b5e7365cb7a51fc46 Mon Sep 17 00:00:00 2001 From: Bertrand Songis Date: Wed, 8 Jun 2016 20:26:30 +0200 Subject: [PATCH] [Taranis] Trainer / Trainee again OK. Not tested on Horus --- radio/src/datastructs.h | 2 +- radio/src/myeeprom.h | 2 + radio/src/pulses/dsm2_arm.cpp | 2 +- radio/src/pulses/ppm_arm.cpp | 42 ++---- radio/src/pulses/pulses_arm.cpp | 119 ++++++++++------- radio/src/pulses/pulses_arm.h | 27 ++-- radio/src/targets/horus/board_horus.h | 5 - radio/src/targets/horus/extmodule_driver.cpp | 5 +- radio/src/targets/horus/hal.h | 12 +- radio/src/targets/horus/pulses_driver.cpp | 19 ++- radio/src/targets/horus/trainer_driver.cpp | 104 ++++++++------- radio/src/targets/sky9x/pulses_driver.cpp | 123 ++++++++++-------- radio/src/targets/taranis/board_taranis.h | 5 - .../src/targets/taranis/extmodule_driver.cpp | 18 +-- radio/src/targets/taranis/hal.h | 12 +- radio/src/targets/taranis/pulses_driver.cpp | 13 +- radio/src/targets/taranis/trainer_driver.cpp | 111 +++++++++------- 17 files changed, 332 insertions(+), 289 deletions(-) diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h index 994db9137..fc1c656b2 100644 --- a/radio/src/datastructs.h +++ b/radio/src/datastructs.h @@ -694,7 +694,7 @@ PACK(struct ModuleData { union { struct { int8_t delay:6; - uint8_t pulsePol:1; // For PXX: false = internal antenna, true = exetrnal antenna + uint8_t pulsePol:1; // For PXX: false = internal antenna, true = external antenna uint8_t outputType:1; // false = open drain, true = push pull int8_t frameLength; } ppm; diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h index 66b1e8443..71dd5ab26 100644 --- a/radio/src/myeeprom.h +++ b/radio/src/myeeprom.h @@ -53,6 +53,8 @@ #define GVAR_VALUE(gv, fm) g_model.flightModeData[fm].gvars[gv] #endif +#define GET_PPM_POLARITY(idx) g_model.moduleData[idx].ppm.pulsePol +#define GET_PPM_DELAY(idx) (g_model.moduleData[idx].ppm.delay * 50 + 300) #define SET_DEFAULT_PPM_FRAME_LENGTH(idx) g_model.moduleData[idx].ppm.frameLength = 4 * max((int8_t)0, g_model.moduleData[idx].channelsCount) #if defined(PCBHORUS) diff --git a/radio/src/pulses/dsm2_arm.cpp b/radio/src/pulses/dsm2_arm.cpp index 263a06e9d..a56da8519 100644 --- a/radio/src/pulses/dsm2_arm.cpp +++ b/radio/src/pulses/dsm2_arm.cpp @@ -43,7 +43,7 @@ void _send_1(uint8_t v) else v -= 2; - *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = v; + *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = v - 1; modulePulsesData[EXTERNAL_MODULE].dsm2.index += 1; modulePulsesData[EXTERNAL_MODULE].dsm2.rest -= v; } diff --git a/radio/src/pulses/ppm_arm.cpp b/radio/src/pulses/ppm_arm.cpp index 9fb84668f..5b670d04d 100644 --- a/radio/src/pulses/ppm_arm.cpp +++ b/radio/src/pulses/ppm_arm.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -20,7 +20,8 @@ #include "opentx.h" -void setupPulsesPPM(uint8_t port) // Don't enable interrupts through here +template +void setupPulsesPPM(uint8_t port, PpmPulsesData * ppmPulsesData) { int16_t PPM_range = g_model.extendedLimits ? (512*LIMIT_EXT_PERCENT/100) * 2 : 512 * 2; //range of 0.7..1.7msec @@ -31,19 +32,6 @@ void setupPulsesPPM(uint8_t port) // Don't enable interrupts t uint32_t firstCh = g_model.moduleData[port].channelsStart; uint32_t lastCh = min(NUM_CHNOUT, firstCh + 8 + g_model.moduleData[port].channelsCount); -#if defined(PCBSKY9X) - // TODO move register stuff to driver - register Pwm *pwmptr = PWM; - uint32_t pwmCh = (port == EXTERNAL_MODULE ? 3 : 1); - pwmptr->PWM_CH_NUM[pwmCh].PWM_CDTYUPD = (g_model.moduleData[port].ppm.delay * 50 + 300) * 2; //Stoplen *2 - if (g_model.moduleData[port].ppm.pulsePol) - pwmptr->PWM_CH_NUM[pwmCh].PWM_CMR &= ~0x00000200 ; // CPOL - else - pwmptr->PWM_CH_NUM[pwmCh].PWM_CMR |= 0x00000200 ; // CPOL -#endif - - PpmPulsesData * ppmPulsesData = (port == TRAINER_MODULE ? &trainerPulsesData.ppm : &modulePulsesData[port].ppm); - #if defined(CPUSTM32) ppmPulsesData->ptr = ppmPulsesData->pulses; #else @@ -70,22 +58,14 @@ void setupPulsesPPM(uint8_t port) // Don't enable interrupts t *ptr = rest; *(ptr + 1) = 0; #endif +} -#if defined(CPUSTM32) - rest -= 1000; - uint32_t ppmDelay = (g_model.moduleData[port].ppm.delay * 50 + 300) * 2; - // set idle time, ppm delay and ppm polarity - if (port == TRAINER_MODULE) { - set_trainer_ppm_parameters(rest, ppmDelay, !g_model.moduleData[TRAINER_MODULE].ppm.pulsePol); // ppmPulsePol: 0 - positive, 1 - negative - } - else if (port == EXTERNAL_MODULE) { - set_external_ppm_parameters(rest, ppmDelay, !g_model.moduleData[EXTERNAL_MODULE].ppm.pulsePol); - } -#endif +void setupPulsesPPMModule(uint8_t port) +{ + setupPulsesPPM(port, &modulePulsesData[port].ppm); +} -#if defined(TARANIS_INTERNAL_PPM) - else if (port == INTERNAL_MODULE) { - set_internal_ppm_parameters(rest, ppmDelay, !g_model.moduleData[INTERNAL_MODULE].ppm.pulsePol); - } -#endif // #if defined(TARANIS_INTERNAL_PPM) +void setupPulsesPPMTrainer() +{ + setupPulsesPPM(TRAINER_MODULE, &trainerPulsesData.ppm); } diff --git a/radio/src/pulses/pulses_arm.cpp b/radio/src/pulses/pulses_arm.cpp index 44087b6fd..adfc3030c 100644 --- a/radio/src/pulses/pulses_arm.cpp +++ b/radio/src/pulses/pulses_arm.cpp @@ -2,7 +2,7 @@ * Copyright (C) OpenTX * * Based on code named - * th9x - http://code.google.com/p/th9x + * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * @@ -28,16 +28,14 @@ uint8_t moduleFlag[NUM_MODULES] = { 0 }; ModulePulsesData modulePulsesData[NUM_MODULES] __DMA; TrainerPulsesData trainerPulsesData __DMA; -void setupPulses(uint8_t port) +uint8_t getRequiredProtocol(uint8_t port) { uint8_t required_protocol; - heartbeat |= (HEART_TIMER_PULSES << port); - switch (port) { #if defined(PCBTARANIS) || defined(PCBHORUS) case INTERNAL_MODULE: - #if defined(TARANIS_INTERNAL_PPM) +#if defined(TARANIS_INTERNAL_PPM) switch (g_model.moduleData[INTERNAL_MODULE].type) { case MODULE_TYPE_PPM: required_protocol = PROTO_PPM; @@ -49,9 +47,9 @@ void setupPulses(uint8_t port) required_protocol = PROTO_NONE; break; } - #else +#else required_protocol = g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF ? PROTO_NONE : PROTO_PXX; - #endif +#endif break; #endif @@ -111,12 +109,23 @@ void setupPulses(uint8_t port) } #endif - if (s_current_protocol[port] != required_protocol) { + return required_protocol; +} +void setupPulses(uint8_t port) +{ + bool init_needed = false; + uint8_t required_protocol = getRequiredProtocol(port); + + heartbeat |= (HEART_TIMER_PULSES << port); + + if (s_current_protocol[port] != required_protocol) { + init_needed = true; switch (s_current_protocol[port]) { // stop existing protocol hardware case PROTO_PXX: disable_pxx(port); break; + #if defined(DSM2) case PROTO_DSM2_LP45: case PROTO_DSM2_DSM2: @@ -124,30 +133,79 @@ void setupPulses(uint8_t port) disable_dsm2(port); break; #endif + #if defined(CROSSFIRE) case PROTO_CROSSFIRE: disable_crossfire(port); break; #endif + #if defined(MULTIMODULE) case PROTO_MULTIMODULE: disable_dsm2(port); break; #endif + case PROTO_PPM: disable_ppm(port); break; + default: disable_no_pulses(port); break; } - s_current_protocol[port] = required_protocol; + } + // Set up output data here + switch (required_protocol) { + case PROTO_PXX: + setupPulsesPXX(port); + scheduleNextMixerCalculation(port, 9); + break; + +#if defined(DSM2) + case PROTO_DSM2_LP45: + case PROTO_DSM2_DSM2: + case PROTO_DSM2_DSMX: + setupPulsesDSM2(port); + scheduleNextMixerCalculation(port, 11); + break; +#endif + +#if defined(CROSSFIRE) + case PROTO_CROSSFIRE: + if (telemetryProtocol == PROTOCOL_PULSES_CROSSFIRE && !init_needed) { + uint8_t * crossfire = modulePulsesData[port].crossfire.pulses; + createCrossfireFrame(crossfire, &channelOutputs[g_model.moduleData[port].channelsStart]); + sportSendBuffer(crossfire, CROSSFIRE_FRAME_LEN); + } + scheduleNextMixerCalculation(port, CROSSFIRE_FRAME_PERIOD); + break; +#endif + +#if defined(MULTIMODULE) + case PROTO_MULTIMODULE: + setupPulsesMultimodule(port); + scheduleNextMixerCalculation(port, 11); + break; +#endif + + case PROTO_PPM: + setupPulsesPPMModule(port); + scheduleNextMixerCalculation(port, (45+g_model.moduleData[port].ppm.frameLength)/2); + break; + + default: + break; + } + + if (init_needed) { switch (required_protocol) { // Start new protocol hardware here case PROTO_PXX: init_pxx(port); break; + #if defined(DSM2) case PROTO_DSM2_LP45: case PROTO_DSM2_DSM2: @@ -155,16 +213,19 @@ void setupPulses(uint8_t port) init_dsm2(port); break; #endif + #if defined(CROSSFIRE) case PROTO_CROSSFIRE: init_crossfire(port); break; #endif + #if defined(MULTIMODULE) case PROTO_MULTIMODULE: init_dsm2(port); break; #endif + case PROTO_PPM: init_ppm(port); break; @@ -174,44 +235,4 @@ void setupPulses(uint8_t port) break; } } - - // Set up output data here - switch (required_protocol) { - case PROTO_PXX: - setupPulsesPXX(port); - scheduleNextMixerCalculation(port, 9); - break; -#if defined(DSM2) - case PROTO_DSM2_LP45: - case PROTO_DSM2_DSM2: - case PROTO_DSM2_DSMX: - setupPulsesDSM2(port); - scheduleNextMixerCalculation(port, 11); - break; -#endif -#if defined(CROSSFIRE) - case PROTO_CROSSFIRE: - { - if (telemetryProtocol == PROTOCOL_PULSES_CROSSFIRE) { - uint8_t * crossfire = modulePulsesData[port].crossfire.pulses; - createCrossfireFrame(crossfire, &channelOutputs[g_model.moduleData[port].channelsStart]); - sportSendBuffer(crossfire, CROSSFIRE_FRAME_LEN); - scheduleNextMixerCalculation(port, CROSSFIRE_FRAME_PERIOD); - } - break; - } -#endif -#if defined(MULTIMODULE) - case PROTO_MULTIMODULE: - setupPulsesMultimodule(port); - scheduleNextMixerCalculation(port, 11); - break; -#endif - case PROTO_PPM: - setupPulsesPPM(port); - scheduleNextMixerCalculation(port, (45+g_model.moduleData[port].ppm.frameLength)/2); - break ; - default: - break; - } } diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h index 3e6a467d5..4fd8b7cc8 100644 --- a/radio/src/pulses/pulses_arm.h +++ b/radio/src/pulses/pulses_arm.h @@ -22,30 +22,32 @@ #define _PULSES_ARM_H_ #if NUM_MODULES == 2 - #define MODULES_INIT(...) __VA_ARGS__, __VA_ARGS__ + #define MODULES_INIT(...) __VA_ARGS__, __VA_ARGS__ #else - #define MODULES_INIT(...) __VA_ARGS__ + #define MODULES_INIT(...) __VA_ARGS__ #endif #if defined(PCBHORUS) - #define pulse_duration_t uint32_t + #define pulse_duration_t uint32_t + #define trainer_pulse_duration_t uint16_t #else - #define pulse_duration_t uint16_t + #define pulse_duration_t uint16_t + #define trainer_pulse_duration_t uint16_t #endif extern uint8_t s_current_protocol[NUM_MODULES]; extern uint8_t s_pulses_paused; extern uint16_t failsafeCounter[NUM_MODULES]; -PACK(struct PpmPulsesData { - pulse_duration_t pulses[20]; - pulse_duration_t * ptr; +PACK(template struct PpmPulsesData { + T pulses[20]; + T * ptr; }); #if defined(PPM_PIN_SERIAL) PACK(struct PxxSerialPulsesData { uint8_t pulses[64]; - uint8_t *ptr; + uint8_t * ptr; uint16_t pcmValue; uint16_t pcmCrc; uint32_t pcmOnesCount; @@ -55,7 +57,7 @@ PACK(struct PxxSerialPulsesData { PACK(struct Dsm2SerialPulsesData { uint8_t pulses[64]; - uint8_t *ptr; + uint8_t * ptr; uint8_t serialByte ; uint8_t serialBitCount; }); @@ -113,7 +115,7 @@ union ModulePulsesData { #if defined(PPM_PIN_UART) PxxUartPulsesData pxx_uart; #endif - PpmPulsesData ppm; + PpmPulsesData ppm; CrossfirePulsesData crossfire; } __DMA; @@ -126,7 +128,7 @@ union ModulePulsesData { extern ModulePulsesData modulePulsesData[NUM_MODULES]; union TrainerPulsesData { - PpmPulsesData ppm; + PpmPulsesData ppm; }; extern TrainerPulsesData trainerPulsesData; @@ -136,7 +138,8 @@ void setupPulses(uint8_t port); void setupPulsesDSM2(uint8_t port); void setupPulsesMultimodule(uint8_t port); void setupPulsesPXX(uint8_t port); -void setupPulsesPPM(uint8_t port); +void setupPulsesPPMModule(uint8_t port); +void setupPulsesPPMTrainer(); void sendByteDsm2(uint8_t b); void putDsm2Flush(); void putDsm2SerialBit(uint8_t bit); diff --git a/radio/src/targets/horus/board_horus.h b/radio/src/targets/horus/board_horus.h index dab27e230..f09b657f5 100644 --- a/radio/src/targets/horus/board_horus.h +++ b/radio/src/targets/horus/board_horus.h @@ -166,14 +166,10 @@ void SDRAM_Init(void); #define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET) #define IS_UART_MODULE(port) (port == INTERNAL_MODULE) -// void setupPulses(uint8_t port); -// void setupPulsesPPM(uint8_t port); -// void setupPulsesPXX(uint8_t port); void init_no_pulses(uint32_t port); void disable_no_pulses(uint32_t port); void init_ppm( uint32_t module_index ); void disable_ppm( uint32_t module_index ); -void set_external_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive); void init_pxx( uint32_t module_index ); void disable_pxx( uint32_t module_index ); void init_dsm2( uint32_t module_index ); @@ -188,7 +184,6 @@ void init_trainer_capture(void); void stop_trainer_capture(void); void init_cppm_on_heartbeat_capture(void); void stop_cppm_on_heartbeat_capture(void); -void set_trainer_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive); // Keys driver void keysInit(void); diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp index 586f2bb12..3cfd4559a 100644 --- a/radio/src/targets/horus/extmodule_driver.cpp +++ b/radio/src/targets/horus/extmodule_driver.cpp @@ -94,14 +94,13 @@ void extmodulePpmStart() EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - EXTMODULE_TIMER->ARR = 41000; + EXTMODULE_TIMER->ARR = 45000; // CH1 PWM mode 1, CH1 out is OFF if CNTCCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 EXTMODULE_TIMER->EGR = 1; // Reloads register vales now EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; // Start timer - setupPulsesPPM(EXTERNAL_MODULE); extmoduleSendNextFrame(); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); @@ -143,7 +142,6 @@ void extmodulePxxStart() EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - setupPulsesPXX(EXTERNAL_MODULE); extmoduleSendNextFrame(); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); @@ -179,7 +177,6 @@ void extmoduleDsm2Start() EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - setupPulsesDSM2(EXTERNAL_MODULE); extmoduleSendNextFrame(); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 864c5e021..3e15d91c7 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -305,18 +305,26 @@ #define EXTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) // Trainer Port -#define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC) +#define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA1) #define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM3 #define TRAINER_GPIO GPIOC #define TRAINER_GPIO_PIN_IN GPIO_Pin_6 // PC.06 +#define TRAINER_GPIO_PinSource_IN GPIO_PinSource6 #define TRAINER_GPIO_PIN_OUT GPIO_Pin_7 // PC.07 +#define TRAINER_GPIO_PinSource_OUT GPIO_PinSource7 #define TRAINER_GPIO_DETECT GPIOB #define TRAINER_GPIO_PIN_DETECT GPIO_Pin_4 // PB.04 #define TRAINER_TIMER TIM3 #define TRAINER_TIMER_IRQn TIM3_IRQn #define TRAINER_TIMER_IRQHandler TIM3_IRQHandler -#define TRAINER_GPIO_PinSource_IN GPIO_PinSource6 #define TRAINER_GPIO_AF GPIO_AF_TIM3 +#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_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) // Heartbeat #define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD diff --git a/radio/src/targets/horus/pulses_driver.cpp b/radio/src/targets/horus/pulses_driver.cpp index 8b971cc53..16cb3b19f 100644 --- a/radio/src/targets/horus/pulses_driver.cpp +++ b/radio/src/targets/horus/pulses_driver.cpp @@ -159,8 +159,6 @@ void intmodulePxxStart() INTERNAL_MODULE_ON(); - setupPulsesPXX(INTERNAL_MODULE); - NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */; @@ -195,17 +193,16 @@ void intmodulePxxStart() // Timer INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - INTMODULE_TIMER->ARR = 18000; // 9mS - INTMODULE_TIMER->CCR2 = 15000; // Update time + INTMODULE_TIMER->ARR = 18000; // 9mS + INTMODULE_TIMER->CCR2 = 15000; // Update time INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) INTMODULE_TIMER->CCER = TIM_CCER_CC3E; INTMODULE_TIMER->CCER = TIM_CCER_CC3E; - INTMODULE_TIMER->CCMR2 = 0; - INTMODULE_TIMER->EGR = 1; // Restart + INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag + INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p + INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; @@ -227,7 +224,7 @@ extern "C" void INTMODULE_TIMER_CC_IRQHandler() DEBUG_INTERRUPT(INT_TIM1CC); DEBUG_TIMER_SAMPLE(debugTimerIntPulses); DEBUG_TIMER_START(debugTimerIntPulsesDuration); - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // stop this interrupt + // INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // stop this interrupt INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag setupPulses(INTERNAL_MODULE); @@ -239,7 +236,7 @@ extern "C" void INTMODULE_TIMER_CC_IRQHandler() DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR); DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses); - DMA_InitStructure.DMA_BufferSize = (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx_uart.ptr - (uint8_t *)modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses; + DMA_InitStructure.DMA_BufferSize = modulePulsesData[INTERNAL_MODULE].pxx_uart.ptr - modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; @@ -256,6 +253,6 @@ extern "C" void INTMODULE_TIMER_CC_IRQHandler() USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE); } - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; + // INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; DEBUG_TIMER_STOP(debugTimerIntPulsesDuration); } diff --git a/radio/src/targets/horus/trainer_driver.cpp b/radio/src/targets/horus/trainer_driver.cpp index ac0463ec6..0d600b725 100644 --- a/radio/src/targets/horus/trainer_driver.cpp +++ b/radio/src/targets/horus/trainer_driver.cpp @@ -20,49 +20,46 @@ #include "opentx.h" -#define setupTrainerPulses() setupPulsesPPM(TRAINER_MODULE) +void trainerSendNextFrame(); void init_trainer_ppm() { - trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses; + GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_GPIO_PinSource_OUT, TRAINER_GPIO_AF); - configure_pins(TRAINER_GPIO_PIN_OUT, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_2 | PIN_OS25); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = TRAINER_GPIO_PIN_OUT; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure); 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->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS + TRAINER_TIMER->ARR = 45000; TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 TRAINER_TIMER->BDTR = TIM_BDTR_MOE; TRAINER_TIMER->EGR = 1; + TRAINER_TIMER->DIER |= TIM_DIER_UDE; + TRAINER_TIMER->CR1 |= TIM_CR1_CEN; - 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; + setupPulsesPPMTrainer(); + trainerSendNextFrame(); - TRAINER_TIMER->CR1 = TIM_CR1_CEN; + NVIC_EnableIRQ(TRAINER_DMA_IRQn); + NVIC_SetPriority(TRAINER_DMA_IRQn, 7); NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); } void stop_trainer_ppm() { - configure_pins(TRAINER_GPIO_PIN_OUT, PIN_INPUT | PIN_PORTC); // Pin as input - TRAINER_TIMER->DIER = 0; // Stop Interrupt - TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter - NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt -} + NVIC_DisableIRQ(TRAINER_DMA_IRQn); + NVIC_DisableIRQ(TRAINER_TIMER_IRQn); -void set_trainer_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) -{ - TRAINER_TIMER->CCR1 = idleTime; - TRAINER_TIMER->CCR2 = delay; - TRAINER_TIMER->CCER = TIM_CCER_CC2E | (positive ? TIM_CCER_CC2P : 0); + TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + TRAINER_TIMER->DIER = 0; // Stop Interrupt + TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter } void init_trainer_capture() @@ -85,18 +82,51 @@ void init_trainer_capture() TRAINER_TIMER->SR &= ~TIM_SR_CC1IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; TRAINER_TIMER->CR1 = TIM_CR1_CEN; + NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); } void stop_trainer_capture() { + NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt + TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter TRAINER_TIMER->DIER = 0; // Stop Interrupt - NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt } -#if !defined(SIMU) +void trainerSendNextFrame() +{ + TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2; + TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P); + + 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 +} + +extern "C" void TRAINER_DMA_IRQHandler() +{ + if (!DMA_GetITStatus(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC)) + return; + + DMA_ClearITPendingBit(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC); + + uint32_t arr = TRAINER_TIMER->ARR; + if (arr > 5000) { + TRAINER_TIMER->CCR1 = arr - 4000; // 2mS in advance + TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag + TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt + } + else { + setupPulsesPPMTrainer(); + trainerSendNextFrame(); + } +} + extern "C" void TRAINER_TIMER_IRQHandler() { DEBUG_INTERRUPT(INT_TRAINER); @@ -122,23 +152,8 @@ extern "C" void TRAINER_TIMER_IRQHandler() // 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 - } + setupPulsesPPMTrainer(); + trainerSendNextFrame(); } } @@ -159,7 +174,6 @@ extern "C" void HEARTBEAT_TIMER_IRQHandler() captureTrainerPulses(capture); } } -#endif void init_cppm_on_heartbeat_capture(void) { diff --git a/radio/src/targets/sky9x/pulses_driver.cpp b/radio/src/targets/sky9x/pulses_driver.cpp index b6d5a79df..057284ef0 100644 --- a/radio/src/targets/sky9x/pulses_driver.cpp +++ b/radio/src/targets/sky9x/pulses_driver.cpp @@ -20,50 +20,68 @@ #include "opentx.h" +void setExternalModulePolarity() +{ + register Pwm * pwmptr = PWM; + pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS + if (GET_PPM_POLARITY(EXTERNAL_MODULE)) + pwmptr->PWM_CH_NUM[3].PWM_CMR &= ~0x00000200; // CPOL + else + pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200; // CPOL +} + +void setExtraModulePolarity() +{ + register Pwm * pwmptr = PWM; + pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE) * 2; // Duty in half uS + if (GET_PPM_POLARITY(EXTRA_MODULE)) + pwmptr->PWM_CH_NUM[1].PWM_CMR &= ~0x00000200; // CPOL + else + pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200; // CPOL +} + void module_output_active() { - register Pio *pioptr = PIOA ; - pioptr->PIO_ABCDSR[0] &= ~PIO_PA17 ; // Peripheral C - pioptr->PIO_ABCDSR[1] |= PIO_PA17 ; // Peripheral C - pioptr->PIO_PDR = PIO_PA17 ; // Disable bit A17 Assign to peripheral + register Pio *pioptr = PIOA; + pioptr->PIO_ABCDSR[0] &= ~PIO_PA17; // Peripheral C + pioptr->PIO_ABCDSR[1] |= PIO_PA17; // Peripheral C + pioptr->PIO_PDR = PIO_PA17; // Disable bit A17 Assign to peripheral #if defined(REVX) if (g_model.moduleData[EXTERNAL_MODULE].ppm.outputType) { - pioptr->PIO_MDDR = PIO_PA17 ; // Push Pull O/p in A17 + pioptr->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17 } else { - pioptr->PIO_MDER = PIO_PA17 ; // Open Drain O/p in A17 + pioptr->PIO_MDER = PIO_PA17; // Open Drain O/p in A17 } #else - pioptr->PIO_MDDR = PIO_PA17 ; // Push Pull O/p in A17 + pioptr->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17 #endif - pioptr->PIO_PUER = PIO_PA17 ; // With pull up + pioptr->PIO_PUER = PIO_PA17; // With pull up } void init_main_ppm(uint32_t period, uint32_t out_enable) { - register Pwm *pwmptr ; + register Pwm * pwmptr; - setupPulsesPPM(EXTERNAL_MODULE) ; + setupPulsesPPMModule(EXTERNAL_MODULE); if (out_enable) { module_output_active(); } - pwmptr = PWM ; + pwmptr = PWM; // PWM3 for PPM output - pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B ; // CLKA - if (!g_model.moduleData[EXTERNAL_MODULE].ppm.pulsePol) { - 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].ppm.delay*100+600; // Duty in half uS - pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = g_model.moduleData[EXTERNAL_MODULE].ppm.delay*100+600; // Duty in half uS - pwmptr->PWM_ENA = PWM_ENA_CHID3 ; // Enable channel 3 - pwmptr->PWM_IER1 = PWM_IER1_CHID3 ; + pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B; // CLKA + 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 = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // 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) ; + setExternalModulePolarity(); + + NVIC_SetPriority(PWM_IRQn, 3 ); + NVIC_EnableIRQ(PWM_IRQn); } void disable_main_ppm() @@ -78,17 +96,17 @@ void init_second_ppm(uint32_t period) #if !defined(REVA) // PWM1 for PPM2 register Pwm * pwmptr = PWM; - 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].ppm.pulsePol) { - pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200 ; // CPOL + 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 (!GET_PPM_POLARITY(EXTRA_MODULE)) { + 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].ppm.delay*100+600 ; // Duty - pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = g_model.moduleData[EXTRA_MODULE].ppm.delay*100+600 ; // Duty - pwmptr->PWM_ENA = PWM_ENA_CHID1 ; // Enable channel 1 - pwmptr->PWM_IER1 = PWM_IER1_CHID1 ; + 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 = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty + pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty + pwmptr->PWM_ENA = PWM_ENA_CHID1; // Enable channel 1 + pwmptr->PWM_IER1 = PWM_IER1_CHID1; #endif } @@ -96,8 +114,8 @@ void disable_second_ppm() { #if !defined(REVA) register Pio * pioptr = PIOC; - pioptr->PIO_PER = PIO_PC15 ; // Assign C17 to PIO - PWM->PWM_IDR1 = PWM_IDR1_CHID1 ; + pioptr->PIO_PER = PIO_PC15; // Assign C17 to PIO + PWM->PWM_IDR1 = PWM_IDR1_CHID1; #endif } @@ -145,18 +163,18 @@ void disable_ppm(uint32_t port) // TD is on PA17, peripheral A void init_ssc() { - register Ssc * sscptr ; + register Ssc * sscptr; - PMC->PMC_PCER0 |= 0x00400000L ; // Enable peripheral clock to SSC + PMC->PMC_PCER0 |= 0x00400000L; // Enable peripheral clock to SSC - configure_pins(PIO_PA17, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA) ; + configure_pins(PIO_PA17, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_A | PIN_PORTA); - sscptr = SSC ; - sscptr->SSC_THR = 0xFF ; // Make the output high. - sscptr->SSC_TFMR = 0x00000027 ; // 0000 0000 0000 0000 0000 0000 1010 0111 (8 bit data, lsb) - sscptr->SSC_CMR = Master_frequency / (125000*2) ; // 8uS per bit - sscptr->SSC_TCMR = 0 ; // 0000 0000 0000 0000 0000 0000 0000 0000 - sscptr->SSC_CR = SSC_CR_TXEN ; + sscptr = SSC; + sscptr->SSC_THR = 0xFF; // Make the output high. + sscptr->SSC_TFMR = 0x00000027; // 0000 0000 0000 0000 0000 0000 1010 0111 (8 bit data, lsb) + sscptr->SSC_CMR = Master_frequency / (125000*2); // 8uS per bit + sscptr->SSC_TCMR = 0; // 0000 0000 0000 0000 0000 0000 0000 0000 + sscptr->SSC_CR = SSC_CR_TXEN; #if defined(REVX) PIOA->PIO_MDER = PIO_PA17; // Open Drain O/p in A17 @@ -167,15 +185,15 @@ void init_ssc() void disable_ssc() { - register Pio *pioptr ; - register Ssc *sscptr ; + register Pio *pioptr; + register Ssc *sscptr; // Revert back to pwm output - pioptr = PIOA ; - pioptr->PIO_PER = PIO_PA17 ; // Assign A17 to PIO + pioptr = PIOA; + pioptr->PIO_PER = PIO_PA17; // Assign A17 to PIO - sscptr = SSC ; - sscptr->SSC_CR = SSC_CR_TXDIS ; + sscptr = SSC; + sscptr->SSC_CR = SSC_CR_TXDIS; } void init_pxx(uint32_t port) @@ -244,6 +262,7 @@ extern "C" void PWM_IRQHandler(void) pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS if (period != 2500 * 2) { setupPulses(EXTERNAL_MODULE); + setExternalModulePolarity(); } else { // Kick off serial output here @@ -281,6 +300,7 @@ extern "C" void PWM_IRQHandler(void) default: pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++; if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) { + setExternalModulePolarity(); setupPulses(EXTERNAL_MODULE); } break; @@ -292,7 +312,8 @@ extern "C" void PWM_IRQHandler(void) if (reason & PWM_ISR1_CHID1) { pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = *modulePulsesData[EXTRA_MODULE].ppm.ptr++; if (*modulePulsesData[EXTRA_MODULE].ppm.ptr == 0) { - setupPulsesPPM(EXTRA_MODULE); + setupPulsesPPMModule(EXTRA_MODULE); + setExtraModulePolarity(); } } #endif diff --git a/radio/src/targets/taranis/board_taranis.h b/radio/src/targets/taranis/board_taranis.h index 66390b053..931c27633 100644 --- a/radio/src/targets/taranis/board_taranis.h +++ b/radio/src/targets/taranis/board_taranis.h @@ -193,10 +193,6 @@ void init_no_pulses(uint32_t port); void disable_no_pulses(uint32_t port); void init_ppm( uint32_t module_index ); void disable_ppm( uint32_t module_index ); -void set_external_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive); -#if defined(TARANIS_INTERNAL_PPM) - void set_internal_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive); -#endif void init_pxx( uint32_t module_index ); void disable_pxx( uint32_t module_index ); void init_dsm2( uint32_t module_index ); @@ -213,7 +209,6 @@ void init_cppm_on_heartbeat_capture(void); void stop_cppm_on_heartbeat_capture(void); void init_sbus_on_heartbeat_capture(void); void stop_sbus_on_heartbeat_capture(void); -void set_trainer_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive); int sbusGetByte(uint8_t * byte); // Keys driver diff --git a/radio/src/targets/taranis/extmodule_driver.cpp b/radio/src/targets/taranis/extmodule_driver.cpp index a912a26a1..cf591031d 100644 --- a/radio/src/targets/taranis/extmodule_driver.cpp +++ b/radio/src/targets/taranis/extmodule_driver.cpp @@ -82,14 +82,13 @@ void extmodulePpmStart() EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz - EXTMODULE_TIMER->ARR = 41000; + EXTMODULE_TIMER->ARR = 45000; 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->CR1 |= TIM_CR1_CEN; - setupPulsesPPM(EXTERNAL_MODULE); extmoduleSendNextFrame(); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); @@ -98,14 +97,6 @@ void extmodulePpmStart() NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); } -void set_external_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) -{ - EXTMODULE_TIMER->CCR2 = idleTime; - EXTMODULE_TIMER->CCR1 = delay; - // we are using complementary output so logic has to be reversed here - EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE | (positive ? 0 : TIM_CCER_CC1NP); -} - void extmodulePxxStart() { EXTERNAL_MODULE_ON(); @@ -132,7 +123,6 @@ void extmodulePxxStart() EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - setupPulsesPXX(EXTERNAL_MODULE); extmoduleSendNextFrame(); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); @@ -168,7 +158,6 @@ void extmoduleDsm2Start() EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - setupPulsesDSM2(EXTERNAL_MODULE); extmoduleSendNextFrame(); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); @@ -209,6 +198,9 @@ void extmoduleCrossfireStart() void extmoduleSendNextFrame() { if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) { + EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2; + // we are using complementary output so logic has to be reversed here + EXTMODULE_TIMER->CCER = TIM_CCER_CC1NE | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1NP : 0); EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA EXTMODULE_DMA_STREAM->CR |= EXTMODULE_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; EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR); @@ -245,7 +237,7 @@ extern "C" void EXTMODULE_DMA_IRQHandler() DMA_ClearITPendingBit(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC); uint32_t arr = EXTMODULE_TIMER->ARR; - if (arr > 4000) { + if (arr > 5000) { EXTMODULE_TIMER->CCR2 = arr - 4000; // 2mS in advance EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 9b2ea7a43..62a6b6e78 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -377,13 +377,23 @@ #define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM3 #define TRAINER_GPIO GPIOC #define TRAINER_GPIO_PIN_IN GPIO_Pin_8 // PC.08 +#define TRAINER_GPIO_PinSource_IN GPIO_PinSource8 #define TRAINER_GPIO_PIN_OUT GPIO_Pin_9 // PC.09 +#define TRAINER_GPIO_PinSource_OUT GPIO_PinSource9 #define TRAINER_GPIO_DETECT GPIOA #define TRAINER_GPIO_PIN_DETECT GPIO_Pin_8 // PA.08 #define TRAINER_TIMER TIM3 #define TRAINER_TIMER_IRQn TIM3_IRQn -#define TRAINER_GPIO_PinSource_IN GPIO_PinSource8 #define TRAINER_GPIO_AF GPIO_AF_TIM3 +#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_TIMER_IRQn TIM3_IRQn +#define TRAINER_TIMER_IRQHandler TIM3_IRQHandler +#define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) // Serial Port #define SERIAL_RCC_AHB1Periph RCC_AHB1Periph_GPIOB diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp index 4d4c6b979..14d58e8d3 100644 --- a/radio/src/targets/taranis/pulses_driver.cpp +++ b/radio/src/targets/taranis/pulses_driver.cpp @@ -189,7 +189,6 @@ void intmodulePxxStart() INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - setupPulsesPXX(INTERNAL_MODULE); intmoduleSendNextFrame(); NVIC_EnableIRQ(INTMODULE_DMA_IRQn); @@ -215,14 +214,13 @@ void intmodulePpmStart() INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz - INTMODULE_TIMER->ARR = 41000; + INTMODULE_TIMER->ARR = 45000; INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1 INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; INTMODULE_TIMER->EGR = 1; INTMODULE_TIMER->DIER = TIM_DIER_UDE; INTMODULE_TIMER->CR1 = TIM_CR1_CEN; - setupPulsesPPM(INTERNAL_MODULE); intmoduleSendNextFrame(); NVIC_EnableIRQ(INTMODULE_DMA_IRQn); @@ -230,13 +228,6 @@ void intmodulePpmStart() NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); } - -void set_internal_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) -{ - INTMODULE_TIMER->CCR2 = idleTime; - INTMODULE_TIMER->CCR3 = delay; - INTMODULE_TIMER->CCER = TIM_CCER_CC3E | (positive ? TIM_CCER_CC3P : 0); -} #endif // defined(TARANIS_INTERNAL_PPM) void intmoduleSendNextFrame() @@ -251,6 +242,8 @@ void intmoduleSendNextFrame() } #if defined(TARANIS_INTERNAL_PPM) else if (s_current_protocol[INTERNAL_MODULE] == PROTO_PPM) { + INTMODULE_TIMER->CCR3 = GET_PPM_DEAY(INTERNAL_MODULE)*2; + INTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_PPM_POLARITY(INTERNAL_MODULE) ? 0 : TIM_CCER_CC3P); INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA INTMODULE_DMA_STREAM->CR |= INTMODULE_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; INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR); diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp index f4e2cdce2..5f9901268 100644 --- a/radio/src/targets/taranis/trainer_driver.cpp +++ b/radio/src/targets/taranis/trainer_driver.cpp @@ -22,62 +22,59 @@ DMAFifo<32> heartbeatFifo __DMA (HEARTBEAT_DMA_Stream); -#define setupTrainerPulses() setupPulsesPPM(TRAINER_MODULE) +void trainerSendNextFrame(); void init_trainer_ppm() { - trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses; + GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_GPIO_PinSource_OUT, TRAINER_GPIO_AF); - configure_pins(TRAINER_GPIO_PIN_OUT, PIN_PERIPHERAL | PIN_PORTC | PIN_PER_2 | PIN_OS25); + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_InitStructure.GPIO_Pin = TRAINER_GPIO_PIN_OUT; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; + GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; + GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure); 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->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 TRAINER_TIMER->BDTR = TIM_BDTR_MOE; TRAINER_TIMER->EGR = 1; + TRAINER_TIMER->DIER |= TIM_DIER_UDE; + TRAINER_TIMER->CR1 |= TIM_CR1_CEN; - 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; + setupPulsesPPMTrainer(); + trainerSendNextFrame(); - TRAINER_TIMER->CR1 = TIM_CR1_CEN; + NVIC_EnableIRQ(TRAINER_DMA_IRQn); + NVIC_SetPriority(TRAINER_DMA_IRQn, 7); NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); } void stop_trainer_ppm() { - configure_pins(TRAINER_GPIO_PIN_OUT, PIN_INPUT | PIN_PORTC); // Pin as input - TRAINER_TIMER->DIER = 0; // Stop Interrupt - TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter - NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt -} + NVIC_DisableIRQ(TRAINER_DMA_IRQn); + NVIC_DisableIRQ(TRAINER_TIMER_IRQn); -void set_trainer_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) -{ - TRAINER_TIMER->CCR1 = idleTime; - TRAINER_TIMER->CCR4 = delay; - TRAINER_TIMER->CCER = TIM_CCER_CC4E | (positive ? TIM_CCER_CC4P : 0); + TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA + TRAINER_TIMER->DIER = 0; + TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter } void init_trainer_capture() { - GPIO_InitTypeDef GPIO_InitStructure; + GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_GPIO_PinSource_IN, TRAINER_GPIO_AF); + GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = TRAINER_GPIO_PIN_IN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure); - GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_GPIO_PinSource_IN, TRAINER_GPIO_AF); TRAINER_TIMER->ARR = 0xFFFF; TRAINER_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5uS @@ -87,21 +84,55 @@ void init_trainer_capture() TRAINER_TIMER->SR &= ~TIM_SR_CC3IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags TRAINER_TIMER->DIER |= TIM_DIER_CC3IE; TRAINER_TIMER->CR1 = TIM_CR1_CEN; + NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); } void stop_trainer_capture() { + NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt + TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter TRAINER_TIMER->DIER = 0; // Stop Interrupt - NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt } -#if !defined(SIMU) -extern "C" void TIM3_IRQHandler() +void trainerSendNextFrame() +{ + TRAINER_TIMER->CCR4 = GET_PPM_DELAY(TRAINER_MODULE)*2; + TRAINER_TIMER->CCER = TIM_CCER_CC4E | (GET_PPM_POLARITY(TRAINER_MODULE) ? 0 : TIM_CCER_CC4P); + + 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 +} + +extern "C" void TRAINER_DMA_IRQHandler() +{ + if (!DMA_GetITStatus(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC)) + return; + + DMA_ClearITPendingBit(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC); + + uint32_t arr = TRAINER_TIMER->ARR; + if (arr > 5000) { + TRAINER_TIMER->CCR1 = arr - 4000; // 2mS in advance + TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag + TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt + } + else { + setupPulsesPPMTrainer(); + trainerSendNextFrame(); + } +} + +extern "C" void TRAINER_TIMER_IRQHandler() { DEBUG_INTERRUPT(INT_TRAINER); + uint16_t capture = 0; bool doCapture = false; @@ -131,26 +162,10 @@ extern "C" void TIM3_IRQHandler() // 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 - } + setupPulsesPPMTrainer(); + trainerSendNextFrame(); } } -#endif void init_cppm_on_heartbeat_capture(void) {