1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-18 05:45:21 +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 { union {
struct { struct {
int8_t delay:6; 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 uint8_t outputType:1; // false = open drain, true = push pull
int8_t frameLength; int8_t frameLength;
} ppm; } ppm;

View file

@ -53,6 +53,8 @@
#define GVAR_VALUE(gv, fm) g_model.flightModeData[fm].gvars[gv] #define GVAR_VALUE(gv, fm) g_model.flightModeData[fm].gvars[gv]
#endif #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) #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) #if defined(PCBHORUS)

View file

@ -43,7 +43,7 @@ void _send_1(uint8_t v)
else else
v -= 2; 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.index += 1;
modulePulsesData[EXTERNAL_MODULE].dsm2.rest -= v; modulePulsesData[EXTERNAL_MODULE].dsm2.rest -= v;
} }

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX * Copyright (C) OpenTX
* *
* Based on code named * 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 * er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x * gruvin9x - http://code.google.com/p/gruvin9x
* *
@ -20,7 +20,8 @@
#include "opentx.h" #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 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 firstCh = g_model.moduleData[port].channelsStart;
uint32_t lastCh = min<unsigned int>(NUM_CHNOUT, firstCh + 8 + g_model.moduleData[port].channelsCount); 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) #if defined(CPUSTM32)
ppmPulsesData->ptr = ppmPulsesData->pulses; ppmPulsesData->ptr = ppmPulsesData->pulses;
#else #else
@ -70,22 +58,14 @@ void setupPulsesPPM(uint8_t port) // Don't enable interrupts t
*ptr = rest; *ptr = rest;
*(ptr + 1) = 0; *(ptr + 1) = 0;
#endif #endif
}
#if defined(CPUSTM32)
rest -= 1000; void setupPulsesPPMModule(uint8_t port)
uint32_t ppmDelay = (g_model.moduleData[port].ppm.delay * 50 + 300) * 2; {
// set idle time, ppm delay and ppm polarity setupPulsesPPM<pulse_duration_t>(port, &modulePulsesData[port].ppm);
if (port == TRAINER_MODULE) { }
set_trainer_ppm_parameters(rest, ppmDelay, !g_model.moduleData[TRAINER_MODULE].ppm.pulsePol); // ppmPulsePol: 0 - positive, 1 - negative
} void setupPulsesPPMTrainer()
else if (port == EXTERNAL_MODULE) { {
set_external_ppm_parameters(rest, ppmDelay, !g_model.moduleData[EXTERNAL_MODULE].ppm.pulsePol); setupPulsesPPM<trainer_pulse_duration_t>(TRAINER_MODULE, &trainerPulsesData.ppm);
}
#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)
} }

View file

@ -2,7 +2,7 @@
* Copyright (C) OpenTX * Copyright (C) OpenTX
* *
* Based on code named * 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 * er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x * gruvin9x - http://code.google.com/p/gruvin9x
* *
@ -28,16 +28,14 @@ uint8_t moduleFlag[NUM_MODULES] = { 0 };
ModulePulsesData modulePulsesData[NUM_MODULES] __DMA; ModulePulsesData modulePulsesData[NUM_MODULES] __DMA;
TrainerPulsesData trainerPulsesData __DMA; TrainerPulsesData trainerPulsesData __DMA;
void setupPulses(uint8_t port) uint8_t getRequiredProtocol(uint8_t port)
{ {
uint8_t required_protocol; uint8_t required_protocol;
heartbeat |= (HEART_TIMER_PULSES << port);
switch (port) { switch (port) {
#if defined(PCBTARANIS) || defined(PCBHORUS) #if defined(PCBTARANIS) || defined(PCBHORUS)
case INTERNAL_MODULE: case INTERNAL_MODULE:
#if defined(TARANIS_INTERNAL_PPM) #if defined(TARANIS_INTERNAL_PPM)
switch (g_model.moduleData[INTERNAL_MODULE].type) { switch (g_model.moduleData[INTERNAL_MODULE].type) {
case MODULE_TYPE_PPM: case MODULE_TYPE_PPM:
required_protocol = PROTO_PPM; required_protocol = PROTO_PPM;
@ -49,9 +47,9 @@ void setupPulses(uint8_t port)
required_protocol = PROTO_NONE; required_protocol = PROTO_NONE;
break; break;
} }
#else #else
required_protocol = g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF ? PROTO_NONE : PROTO_PXX; required_protocol = g_model.moduleData[INTERNAL_MODULE].rfProtocol == RF_PROTO_OFF ? PROTO_NONE : PROTO_PXX;
#endif #endif
break; break;
#endif #endif
@ -111,12 +109,23 @@ void setupPulses(uint8_t port)
} }
#endif #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 switch (s_current_protocol[port]) { // stop existing protocol hardware
case PROTO_PXX: case PROTO_PXX:
disable_pxx(port); disable_pxx(port);
break; break;
#if defined(DSM2) #if defined(DSM2)
case PROTO_DSM2_LP45: case PROTO_DSM2_LP45:
case PROTO_DSM2_DSM2: case PROTO_DSM2_DSM2:
@ -124,30 +133,79 @@ void setupPulses(uint8_t port)
disable_dsm2(port); disable_dsm2(port);
break; break;
#endif #endif
#if defined(CROSSFIRE) #if defined(CROSSFIRE)
case PROTO_CROSSFIRE: case PROTO_CROSSFIRE:
disable_crossfire(port); disable_crossfire(port);
break; break;
#endif #endif
#if defined(MULTIMODULE) #if defined(MULTIMODULE)
case PROTO_MULTIMODULE: case PROTO_MULTIMODULE:
disable_dsm2(port); disable_dsm2(port);
break; break;
#endif #endif
case PROTO_PPM: case PROTO_PPM:
disable_ppm(port); disable_ppm(port);
break; break;
default: default:
disable_no_pulses(port); disable_no_pulses(port);
break; break;
} }
s_current_protocol[port] = required_protocol; 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 switch (required_protocol) { // Start new protocol hardware here
case PROTO_PXX: case PROTO_PXX:
init_pxx(port); init_pxx(port);
break; break;
#if defined(DSM2) #if defined(DSM2)
case PROTO_DSM2_LP45: case PROTO_DSM2_LP45:
case PROTO_DSM2_DSM2: case PROTO_DSM2_DSM2:
@ -155,16 +213,19 @@ void setupPulses(uint8_t port)
init_dsm2(port); init_dsm2(port);
break; break;
#endif #endif
#if defined(CROSSFIRE) #if defined(CROSSFIRE)
case PROTO_CROSSFIRE: case PROTO_CROSSFIRE:
init_crossfire(port); init_crossfire(port);
break; break;
#endif #endif
#if defined(MULTIMODULE) #if defined(MULTIMODULE)
case PROTO_MULTIMODULE: case PROTO_MULTIMODULE:
init_dsm2(port); init_dsm2(port);
break; break;
#endif #endif
case PROTO_PPM: case PROTO_PPM:
init_ppm(port); init_ppm(port);
break; break;
@ -174,44 +235,4 @@ void setupPulses(uint8_t port)
break; 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_ #define _PULSES_ARM_H_
#if NUM_MODULES == 2 #if NUM_MODULES == 2
#define MODULES_INIT(...) __VA_ARGS__, __VA_ARGS__ #define MODULES_INIT(...) __VA_ARGS__, __VA_ARGS__
#else #else
#define MODULES_INIT(...) __VA_ARGS__ #define MODULES_INIT(...) __VA_ARGS__
#endif #endif
#if defined(PCBHORUS) #if defined(PCBHORUS)
#define pulse_duration_t uint32_t #define pulse_duration_t uint32_t
#define trainer_pulse_duration_t uint16_t
#else #else
#define pulse_duration_t uint16_t #define pulse_duration_t uint16_t
#define trainer_pulse_duration_t uint16_t
#endif #endif
extern uint8_t s_current_protocol[NUM_MODULES]; extern uint8_t s_current_protocol[NUM_MODULES];
extern uint8_t s_pulses_paused; extern uint8_t s_pulses_paused;
extern uint16_t failsafeCounter[NUM_MODULES]; extern uint16_t failsafeCounter[NUM_MODULES];
PACK(struct PpmPulsesData { PACK(template<class T> struct PpmPulsesData {
pulse_duration_t pulses[20]; T pulses[20];
pulse_duration_t * ptr; T * ptr;
}); });
#if defined(PPM_PIN_SERIAL) #if defined(PPM_PIN_SERIAL)
PACK(struct PxxSerialPulsesData { PACK(struct PxxSerialPulsesData {
uint8_t pulses[64]; uint8_t pulses[64];
uint8_t *ptr; uint8_t * ptr;
uint16_t pcmValue; uint16_t pcmValue;
uint16_t pcmCrc; uint16_t pcmCrc;
uint32_t pcmOnesCount; uint32_t pcmOnesCount;
@ -55,7 +57,7 @@ PACK(struct PxxSerialPulsesData {
PACK(struct Dsm2SerialPulsesData { PACK(struct Dsm2SerialPulsesData {
uint8_t pulses[64]; uint8_t pulses[64];
uint8_t *ptr; uint8_t * ptr;
uint8_t serialByte ; uint8_t serialByte ;
uint8_t serialBitCount; uint8_t serialBitCount;
}); });
@ -113,7 +115,7 @@ union ModulePulsesData {
#if defined(PPM_PIN_UART) #if defined(PPM_PIN_UART)
PxxUartPulsesData pxx_uart; PxxUartPulsesData pxx_uart;
#endif #endif
PpmPulsesData ppm; PpmPulsesData<pulse_duration_t> ppm;
CrossfirePulsesData crossfire; CrossfirePulsesData crossfire;
} __DMA; } __DMA;
@ -126,7 +128,7 @@ union ModulePulsesData {
extern ModulePulsesData modulePulsesData[NUM_MODULES]; extern ModulePulsesData modulePulsesData[NUM_MODULES];
union TrainerPulsesData { union TrainerPulsesData {
PpmPulsesData ppm; PpmPulsesData<uint16_t> ppm;
}; };
extern TrainerPulsesData trainerPulsesData; extern TrainerPulsesData trainerPulsesData;
@ -136,7 +138,8 @@ void setupPulses(uint8_t port);
void setupPulsesDSM2(uint8_t port); void setupPulsesDSM2(uint8_t port);
void setupPulsesMultimodule(uint8_t port); void setupPulsesMultimodule(uint8_t port);
void setupPulsesPXX(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 sendByteDsm2(uint8_t b);
void putDsm2Flush(); void putDsm2Flush();
void putDsm2SerialBit(uint8_t bit); 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_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET)
#define IS_UART_MODULE(port) (port == INTERNAL_MODULE) #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 init_no_pulses(uint32_t port);
void disable_no_pulses(uint32_t port); void disable_no_pulses(uint32_t port);
void init_ppm( uint32_t module_index ); void init_ppm( uint32_t module_index );
void disable_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 init_pxx( uint32_t module_index );
void disable_pxx( uint32_t module_index ); void disable_pxx( uint32_t module_index );
void init_dsm2( 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 stop_trainer_capture(void);
void init_cppm_on_heartbeat_capture(void); void init_cppm_on_heartbeat_capture(void);
void stop_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 // Keys driver
void keysInit(void); void keysInit(void);

View file

@ -94,14 +94,13 @@ void extmodulePpmStart()
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) 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) // 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->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->EGR = 1; // Reloads register vales now
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; // Start timer EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; // Start timer
setupPulsesPPM(EXTERNAL_MODULE);
extmoduleSendNextFrame(); extmoduleSendNextFrame();
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
@ -143,7 +142,6 @@ void extmodulePxxStart()
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
setupPulsesPXX(EXTERNAL_MODULE);
extmoduleSendNextFrame(); extmoduleSendNextFrame();
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
@ -179,7 +177,6 @@ void extmoduleDsm2Start()
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
setupPulsesDSM2(EXTERNAL_MODULE);
extmoduleSendNextFrame(); extmoduleSendNextFrame();
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);

View file

@ -305,18 +305,26 @@
#define EXTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1) #define EXTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
// Trainer Port // 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_RCC_APB1Periph RCC_APB1Periph_TIM3
#define TRAINER_GPIO GPIOC #define TRAINER_GPIO GPIOC
#define TRAINER_GPIO_PIN_IN GPIO_Pin_6 // PC.06 #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_PIN_OUT GPIO_Pin_7 // PC.07
#define TRAINER_GPIO_PinSource_OUT GPIO_PinSource7
#define TRAINER_GPIO_DETECT GPIOB #define TRAINER_GPIO_DETECT GPIOB
#define TRAINER_GPIO_PIN_DETECT GPIO_Pin_4 // PB.04 #define TRAINER_GPIO_PIN_DETECT GPIO_Pin_4 // PB.04
#define TRAINER_TIMER TIM3 #define TRAINER_TIMER TIM3
#define TRAINER_TIMER_IRQn TIM3_IRQn #define TRAINER_TIMER_IRQn TIM3_IRQn
#define TRAINER_TIMER_IRQHandler TIM3_IRQHandler #define TRAINER_TIMER_IRQHandler TIM3_IRQHandler
#define TRAINER_GPIO_PinSource_IN GPIO_PinSource6
#define TRAINER_GPIO_AF GPIO_AF_TIM3 #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 // Heartbeat
#define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD #define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD

View file

@ -159,8 +159,6 @@ void intmodulePxxStart()
INTERNAL_MODULE_ON(); INTERNAL_MODULE_ON();
setupPulsesPXX(INTERNAL_MODULE);
NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ; NVIC_InitStructure.NVIC_IRQChannel = INTMODULE_DMA_STREAM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; /* Not used as 4 bits are used for the pre-emption priority. */;
@ -195,17 +193,16 @@ void intmodulePxxStart()
// Timer // Timer
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
INTMODULE_TIMER->ARR = 18000; // 9mS INTMODULE_TIMER->ARR = 18000; // 9mS
INTMODULE_TIMER->CCR2 = 15000; // Update time INTMODULE_TIMER->CCR2 = 15000; // Update time
INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) 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->CCER = TIM_CCER_CC3E; INTMODULE_TIMER->CCER = TIM_CCER_CC3E;
INTMODULE_TIMER->CCMR2 = 0; 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->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
@ -227,7 +224,7 @@ extern "C" void INTMODULE_TIMER_CC_IRQHandler()
DEBUG_INTERRUPT(INT_TIM1CC); DEBUG_INTERRUPT(INT_TIM1CC);
DEBUG_TIMER_SAMPLE(debugTimerIntPulses); DEBUG_TIMER_SAMPLE(debugTimerIntPulses);
DEBUG_TIMER_START(debugTimerIntPulsesDuration); 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 INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag
setupPulses(INTERNAL_MODULE); 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_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR);
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx_uart.pulses); 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_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; 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); USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE);
} }
INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
DEBUG_TIMER_STOP(debugTimerIntPulsesDuration); DEBUG_TIMER_STOP(debugTimerIntPulsesDuration);
} }

View file

@ -20,49 +20,46 @@
#include "opentx.h" #include "opentx.h"
#define setupTrainerPulses() setupPulsesPPM(TRAINER_MODULE) void trainerSendNextFrame();
void init_trainer_ppm() 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; TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN;
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
// setupTrainerPulses() is also configuring registers, TRAINER_TIMER->ARR = 45000;
// 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->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE; // PWM mode 1 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->BDTR = TIM_BDTR_MOE;
TRAINER_TIMER->EGR = 1; TRAINER_TIMER->EGR = 1;
TRAINER_TIMER->DIER |= TIM_DIER_UDE;
TRAINER_TIMER->CR1 |= TIM_CR1_CEN;
TRAINER_TIMER->SR &= ~TIM_SR_UIF; // Clear flag setupPulsesPPMTrainer();
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag trainerSendNextFrame();
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE;
TRAINER_TIMER->DIER |= TIM_DIER_UIE;
TRAINER_TIMER->CR1 = TIM_CR1_CEN; NVIC_EnableIRQ(TRAINER_DMA_IRQn);
NVIC_SetPriority(TRAINER_DMA_IRQn, 7);
NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
} }
void stop_trainer_ppm() void stop_trainer_ppm()
{ {
configure_pins(TRAINER_GPIO_PIN_OUT, PIN_INPUT | PIN_PORTC); // Pin as input NVIC_DisableIRQ(TRAINER_DMA_IRQn);
TRAINER_TIMER->DIER = 0; // Stop Interrupt NVIC_DisableIRQ(TRAINER_TIMER_IRQn);
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
}
void set_trainer_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
{ TRAINER_TIMER->DIER = 0; // Stop Interrupt
TRAINER_TIMER->CCR1 = idleTime; TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
TRAINER_TIMER->CCR2 = delay;
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (positive ? TIM_CCER_CC2P : 0);
} }
void init_trainer_capture() 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->SR &= ~TIM_SR_CC1IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; TRAINER_TIMER->DIER |= TIM_DIER_CC1IE;
TRAINER_TIMER->CR1 = TIM_CR1_CEN; TRAINER_TIMER->CR1 = TIM_CR1_CEN;
NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
} }
void stop_trainer_capture() void stop_trainer_capture()
{ {
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
TRAINER_TIMER->DIER = 0; // Stop Interrupt 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() extern "C" void TRAINER_TIMER_IRQHandler()
{ {
DEBUG_INTERRUPT(INT_TRAINER); DEBUG_INTERRUPT(INT_TRAINER);
@ -122,23 +152,8 @@ extern "C" void TRAINER_TIMER_IRQHandler()
// compare interrupt // compare interrupt
TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
setupPulsesPPMTrainer();
setupTrainerPulses(); trainerSendNextFrame();
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
}
} }
} }
@ -159,7 +174,6 @@ extern "C" void HEARTBEAT_TIMER_IRQHandler()
captureTrainerPulses(capture); captureTrainerPulses(capture);
} }
} }
#endif
void init_cppm_on_heartbeat_capture(void) void init_cppm_on_heartbeat_capture(void)
{ {

View file

@ -20,50 +20,68 @@
#include "opentx.h" #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() void module_output_active()
{ {
register Pio *pioptr = PIOA ; register Pio *pioptr = PIOA;
pioptr->PIO_ABCDSR[0] &= ~PIO_PA17 ; // Peripheral C pioptr->PIO_ABCDSR[0] &= ~PIO_PA17; // Peripheral C
pioptr->PIO_ABCDSR[1] |= PIO_PA17 ; // Peripheral C pioptr->PIO_ABCDSR[1] |= PIO_PA17; // Peripheral C
pioptr->PIO_PDR = PIO_PA17 ; // Disable bit A17 Assign to peripheral pioptr->PIO_PDR = PIO_PA17; // Disable bit A17 Assign to peripheral
#if defined(REVX) #if defined(REVX)
if (g_model.moduleData[EXTERNAL_MODULE].ppm.outputType) { 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 { else {
pioptr->PIO_MDER = PIO_PA17 ; // Open Drain O/p in A17 pioptr->PIO_MDER = PIO_PA17; // Open Drain O/p in A17
} }
#else #else
pioptr->PIO_MDDR = PIO_PA17 ; // Push Pull O/p in A17 pioptr->PIO_MDDR = PIO_PA17; // Push Pull O/p in A17
#endif #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) 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) { if (out_enable) {
module_output_active(); module_output_active();
} }
pwmptr = PWM ; pwmptr = PWM;
// PWM3 for PPM output // PWM3 for PPM output
pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B ; // CLKA pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B; // CLKA
if (!g_model.moduleData[EXTERNAL_MODULE].ppm.pulsePol) { pwmptr->PWM_CH_NUM[3].PWM_CPDR = period; // Period in half uS
pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200 ; // CPOL 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_CH_NUM[3].PWM_CPDR = period ; // Period in half uS pwmptr->PWM_ENA = PWM_ENA_CHID3; // Enable channel 3
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period ; // Period in half uS pwmptr->PWM_IER1 = PWM_IER1_CHID3;
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 ;
NVIC_SetPriority(PWM_IRQn, 3 ) ; setExternalModulePolarity();
NVIC_EnableIRQ(PWM_IRQn) ;
NVIC_SetPriority(PWM_IRQn, 3 );
NVIC_EnableIRQ(PWM_IRQn);
} }
void disable_main_ppm() void disable_main_ppm()
@ -78,17 +96,17 @@ void init_second_ppm(uint32_t period)
#if !defined(REVA) #if !defined(REVA)
// PWM1 for PPM2 // PWM1 for PPM2
register Pwm * pwmptr = PWM; register Pwm * pwmptr = PWM;
configure_pins(PIO_PC15, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP ) ; 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 pwmptr->PWM_CH_NUM[1].PWM_CMR = 0x0000000B; // CLKB
if (!g_model.moduleData[EXTRA_MODULE].ppm.pulsePol) { if (!GET_PPM_POLARITY(EXTRA_MODULE)) {
pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200 ; // CPOL pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200; // CPOL
} }
pwmptr->PWM_CH_NUM[1].PWM_CPDR = period ; // Period pwmptr->PWM_CH_NUM[1].PWM_CPDR = period; // Period
pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = 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_CDTY = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty
pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = g_model.moduleData[EXTRA_MODULE].ppm.delay*100+600 ; // 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_ENA = PWM_ENA_CHID1; // Enable channel 1
pwmptr->PWM_IER1 = PWM_IER1_CHID1 ; pwmptr->PWM_IER1 = PWM_IER1_CHID1;
#endif #endif
} }
@ -96,8 +114,8 @@ void disable_second_ppm()
{ {
#if !defined(REVA) #if !defined(REVA)
register Pio * pioptr = PIOC; register Pio * pioptr = PIOC;
pioptr->PIO_PER = PIO_PC15 ; // Assign C17 to PIO pioptr->PIO_PER = PIO_PC15; // Assign C17 to PIO
PWM->PWM_IDR1 = PWM_IDR1_CHID1 ; PWM->PWM_IDR1 = PWM_IDR1_CHID1;
#endif #endif
} }
@ -145,18 +163,18 @@ void disable_ppm(uint32_t port)
// TD is on PA17, peripheral A // TD is on PA17, peripheral A
void init_ssc() 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;
sscptr->SSC_THR = 0xFF ; // Make the output high. 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_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_CMR = Master_frequency / (125000*2); // 8uS per bit
sscptr->SSC_TCMR = 0 ; // 0000 0000 0000 0000 0000 0000 0000 0000 sscptr->SSC_TCMR = 0; // 0000 0000 0000 0000 0000 0000 0000 0000
sscptr->SSC_CR = SSC_CR_TXEN ; sscptr->SSC_CR = SSC_CR_TXEN;
#if defined(REVX) #if defined(REVX)
PIOA->PIO_MDER = PIO_PA17; // Open Drain O/p in A17 PIOA->PIO_MDER = PIO_PA17; // Open Drain O/p in A17
@ -167,15 +185,15 @@ void init_ssc()
void disable_ssc() void disable_ssc()
{ {
register Pio *pioptr ; register Pio *pioptr;
register Ssc *sscptr ; register Ssc *sscptr;
// Revert back to pwm output // Revert back to pwm output
pioptr = PIOA ; pioptr = PIOA;
pioptr->PIO_PER = PIO_PA17 ; // Assign A17 to PIO pioptr->PIO_PER = PIO_PA17; // Assign A17 to PIO
sscptr = SSC ; sscptr = SSC;
sscptr->SSC_CR = SSC_CR_TXDIS ; sscptr->SSC_CR = SSC_CR_TXDIS;
} }
void init_pxx(uint32_t port) 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 pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
if (period != 2500 * 2) { if (period != 2500 * 2) {
setupPulses(EXTERNAL_MODULE); setupPulses(EXTERNAL_MODULE);
setExternalModulePolarity();
} }
else { else {
// Kick off serial output here // Kick off serial output here
@ -281,6 +300,7 @@ extern "C" void PWM_IRQHandler(void)
default: default:
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++; pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++;
if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) { if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) {
setExternalModulePolarity();
setupPulses(EXTERNAL_MODULE); setupPulses(EXTERNAL_MODULE);
} }
break; break;
@ -292,7 +312,8 @@ extern "C" void PWM_IRQHandler(void)
if (reason & PWM_ISR1_CHID1) { if (reason & PWM_ISR1_CHID1) {
pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = *modulePulsesData[EXTRA_MODULE].ppm.ptr++; pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = *modulePulsesData[EXTRA_MODULE].ppm.ptr++;
if (*modulePulsesData[EXTRA_MODULE].ppm.ptr == 0) { if (*modulePulsesData[EXTRA_MODULE].ppm.ptr == 0) {
setupPulsesPPM(EXTRA_MODULE); setupPulsesPPMModule(EXTRA_MODULE);
setExtraModulePolarity();
} }
} }
#endif #endif

View file

@ -193,10 +193,6 @@ void init_no_pulses(uint32_t port);
void disable_no_pulses(uint32_t port); void disable_no_pulses(uint32_t port);
void init_ppm( uint32_t module_index ); void init_ppm( uint32_t module_index );
void disable_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 init_pxx( uint32_t module_index );
void disable_pxx( uint32_t module_index ); void disable_pxx( uint32_t module_index );
void init_dsm2( 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 stop_cppm_on_heartbeat_capture(void);
void init_sbus_on_heartbeat_capture(void); void init_sbus_on_heartbeat_capture(void);
void stop_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); int sbusGetByte(uint8_t * byte);
// Keys driver // Keys driver

View file

@ -82,14 +82,13 @@ void extmodulePpmStart()
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz 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->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
EXTMODULE_TIMER->EGR = 1; EXTMODULE_TIMER->EGR = 1;
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; EXTMODULE_TIMER->DIER |= TIM_DIER_UDE;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
setupPulsesPPM(EXTERNAL_MODULE);
extmoduleSendNextFrame(); extmoduleSendNextFrame();
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
@ -98,14 +97,6 @@ void extmodulePpmStart()
NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7); 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() void extmodulePxxStart()
{ {
EXTERNAL_MODULE_ON(); EXTERNAL_MODULE_ON();
@ -132,7 +123,6 @@ void extmodulePxxStart()
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
setupPulsesPXX(EXTERNAL_MODULE);
extmoduleSendNextFrame(); extmoduleSendNextFrame();
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
@ -168,7 +158,6 @@ void extmoduleDsm2Start()
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0; EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
setupPulsesDSM2(EXTERNAL_MODULE);
extmoduleSendNextFrame(); extmoduleSendNextFrame();
NVIC_EnableIRQ(EXTMODULE_DMA_IRQn); NVIC_EnableIRQ(EXTMODULE_DMA_IRQn);
@ -209,6 +198,9 @@ void extmoduleCrossfireStart()
void extmoduleSendNextFrame() void extmoduleSendNextFrame()
{ {
if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) { 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 &= ~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->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); 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); DMA_ClearITPendingBit(EXTMODULE_DMA_STREAM, EXTMODULE_DMA_FLAG_TC);
uint32_t arr = EXTMODULE_TIMER->ARR; uint32_t arr = EXTMODULE_TIMER->ARR;
if (arr > 4000) { if (arr > 5000) {
EXTMODULE_TIMER->CCR2 = arr - 4000; // 2mS in advance EXTMODULE_TIMER->CCR2 = arr - 4000; // 2mS in advance
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt

View file

@ -377,13 +377,23 @@
#define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM3 #define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM3
#define TRAINER_GPIO GPIOC #define TRAINER_GPIO GPIOC
#define TRAINER_GPIO_PIN_IN GPIO_Pin_8 // PC.08 #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_PIN_OUT GPIO_Pin_9 // PC.09
#define TRAINER_GPIO_PinSource_OUT GPIO_PinSource9
#define TRAINER_GPIO_DETECT GPIOA #define TRAINER_GPIO_DETECT GPIOA
#define TRAINER_GPIO_PIN_DETECT GPIO_Pin_8 // PA.08 #define TRAINER_GPIO_PIN_DETECT GPIO_Pin_8 // PA.08
#define TRAINER_TIMER TIM3 #define TRAINER_TIMER TIM3
#define TRAINER_TIMER_IRQn TIM3_IRQn #define TRAINER_TIMER_IRQn TIM3_IRQn
#define TRAINER_GPIO_PinSource_IN GPIO_PinSource8
#define TRAINER_GPIO_AF GPIO_AF_TIM3 #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 // Serial Port
#define SERIAL_RCC_AHB1Periph RCC_AHB1Periph_GPIOB #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->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
setupPulsesPXX(INTERNAL_MODULE);
intmoduleSendNextFrame(); intmoduleSendNextFrame();
NVIC_EnableIRQ(INTMODULE_DMA_IRQn); NVIC_EnableIRQ(INTMODULE_DMA_IRQn);
@ -215,14 +214,13 @@ void intmodulePpmStart()
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz 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->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1
INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; INTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
INTMODULE_TIMER->EGR = 1; INTMODULE_TIMER->EGR = 1;
INTMODULE_TIMER->DIER = TIM_DIER_UDE; INTMODULE_TIMER->DIER = TIM_DIER_UDE;
INTMODULE_TIMER->CR1 = TIM_CR1_CEN; INTMODULE_TIMER->CR1 = TIM_CR1_CEN;
setupPulsesPPM(INTERNAL_MODULE);
intmoduleSendNextFrame(); intmoduleSendNextFrame();
NVIC_EnableIRQ(INTMODULE_DMA_IRQn); NVIC_EnableIRQ(INTMODULE_DMA_IRQn);
@ -230,13 +228,6 @@ void intmodulePpmStart()
NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn);
NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); 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) #endif // defined(TARANIS_INTERNAL_PPM)
void intmoduleSendNextFrame() void intmoduleSendNextFrame()
@ -251,6 +242,8 @@ void intmoduleSendNextFrame()
} }
#if defined(TARANIS_INTERNAL_PPM) #if defined(TARANIS_INTERNAL_PPM)
else if (s_current_protocol[INTERNAL_MODULE] == PROTO_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 &= ~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->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); INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);

View file

@ -22,62 +22,59 @@
DMAFifo<32> heartbeatFifo __DMA (HEARTBEAT_DMA_Stream); DMAFifo<32> heartbeatFifo __DMA (HEARTBEAT_DMA_Stream);
#define setupTrainerPulses() setupPulsesPPM(TRAINER_MODULE) void trainerSendNextFrame();
void init_trainer_ppm() 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; TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN;
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
// setupTrainerPulses() is also configuring registers, TRAINER_TIMER->ARR = 45000;
// so it has to be called after the peripheral is enabled
setupTrainerPulses();
TRAINER_TIMER->ARR = *trainerPulsesData.ppm.ptr++;
TRAINER_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5uS
TRAINER_TIMER->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE; // PWM mode 1 TRAINER_TIMER->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE; // PWM mode 1
TRAINER_TIMER->BDTR = TIM_BDTR_MOE; TRAINER_TIMER->BDTR = TIM_BDTR_MOE;
TRAINER_TIMER->EGR = 1; TRAINER_TIMER->EGR = 1;
TRAINER_TIMER->DIER |= TIM_DIER_UDE;
TRAINER_TIMER->CR1 |= TIM_CR1_CEN;
TRAINER_TIMER->SR &= ~TIM_SR_UIF; // Clear flag setupPulsesPPMTrainer();
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag trainerSendNextFrame();
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE;
TRAINER_TIMER->DIER |= TIM_DIER_UIE;
TRAINER_TIMER->CR1 = TIM_CR1_CEN; NVIC_EnableIRQ(TRAINER_DMA_IRQn);
NVIC_SetPriority(TRAINER_DMA_IRQn, 7);
NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
} }
void stop_trainer_ppm() void stop_trainer_ppm()
{ {
configure_pins(TRAINER_GPIO_PIN_OUT, PIN_INPUT | PIN_PORTC); // Pin as input NVIC_DisableIRQ(TRAINER_DMA_IRQn);
TRAINER_TIMER->DIER = 0; // Stop Interrupt NVIC_DisableIRQ(TRAINER_TIMER_IRQn);
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
}
void set_trainer_ppm_parameters(uint32_t idleTime, uint32_t delay, uint32_t positive) TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
{ TRAINER_TIMER->DIER = 0;
TRAINER_TIMER->CCR1 = idleTime; TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
TRAINER_TIMER->CCR4 = delay;
TRAINER_TIMER->CCER = TIM_CCER_CC4E | (positive ? TIM_CCER_CC4P : 0);
} }
void init_trainer_capture() 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_Pin = TRAINER_GPIO_PIN_IN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure); GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure);
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_GPIO_PinSource_IN, TRAINER_GPIO_AF);
TRAINER_TIMER->ARR = 0xFFFF; TRAINER_TIMER->ARR = 0xFFFF;
TRAINER_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5uS 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->SR &= ~TIM_SR_CC3IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags
TRAINER_TIMER->DIER |= TIM_DIER_CC3IE; TRAINER_TIMER->DIER |= TIM_DIER_CC3IE;
TRAINER_TIMER->CR1 = TIM_CR1_CEN; TRAINER_TIMER->CR1 = TIM_CR1_CEN;
NVIC_EnableIRQ(TRAINER_TIMER_IRQn); NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7); NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
} }
void stop_trainer_capture() void stop_trainer_capture()
{ {
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
TRAINER_TIMER->DIER = 0; // Stop Interrupt TRAINER_TIMER->DIER = 0; // Stop Interrupt
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
} }
#if !defined(SIMU) void trainerSendNextFrame()
extern "C" void TIM3_IRQHandler() {
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); DEBUG_INTERRUPT(INT_TRAINER);
uint16_t capture = 0; uint16_t capture = 0;
bool doCapture = false; bool doCapture = false;
@ -131,26 +162,10 @@ extern "C" void TIM3_IRQHandler()
// compare interrupt // compare interrupt
TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
setupPulsesPPMTrainer();
setupTrainerPulses(); trainerSendNextFrame();
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
}
} }
} }
#endif
void init_cppm_on_heartbeat_capture(void) void init_cppm_on_heartbeat_capture(void)
{ {