1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-17 05:15:18 +03:00

[Taranis] Trainer / Trainee again OK. Not tested on Horus

This commit is contained in:
Bertrand Songis 2016-06-08 20:26:30 +02:00
parent 1a7a07dffd
commit 404c5a8553
17 changed files with 334 additions and 291 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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<class T>
void setupPulsesPPM(uint8_t port, PpmPulsesData<T> * 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<unsigned int>(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
#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 setupPulsesPPMModule(uint8_t port)
{
setupPulsesPPM<pulse_duration_t>(port, &modulePulsesData[port].ppm);
}
void setupPulsesPPMTrainer()
{
setupPulsesPPM<trainer_pulse_duration_t>(TRAINER_MODULE, &trainerPulsesData.ppm);
}

View file

@ -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;
}
}

View file

@ -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<class T> 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<pulse_duration_t> ppm;
CrossfirePulsesData crossfire;
} __DMA;
@ -126,7 +128,7 @@ union ModulePulsesData {
extern ModulePulsesData modulePulsesData[NUM_MODULES];
union TrainerPulsesData {
PpmPulsesData ppm;
PpmPulsesData<uint16_t> 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);

View file

@ -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);

View file

@ -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 CNT<CCR1(delay) and ON if bigger (up to AAR,which is pulse length)
EXTMODULE_TIMER->CCMR1 = 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);

View file

@ -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

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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)
{