23 #include <libopencm3/stm32/gpio.h>
24 #include <libopencm3/stm32/rcc.h>
25 #include <libopencm3/stm32/timer.h>
26 #include <libopencm3/stm32/usart.h>
27 #include <libopencm3/cm3/nvic.h>
30 #include "subsystems/radio_control/spektrum_arch.h"
38 INFO(
"Radio-Control now follows PPRZ sign convention: this means you might need to reverese some channels in your transmitter: RollRight / PitchUp / YawRight / FullThrottle / Auto2 are positive deflections")
45 #define SPEKTRUM_CHANNELS_PER_FRAME 7
46 #define MAX_SPEKTRUM_FRAMES 2
47 #define MAX_SPEKTRUM_CHANNELS 16
49 #define ONE_MHZ 1000000
53 #define MASTER_RECEIVER_PULSES 9
54 #define SLAVE_RECEIVER_PULSES 10
56 #define MASTER_RECEIVER_PULSES 5
57 #define SLAVE_RECEIVER_PULSES 6
60 #define TIM_TICS_FOR_100us 100
61 #define MIN_FRAME_SPACE 70 // 7ms
62 #define MAX_BYTE_SPACE 3 // .3ms
66 #define PASTER3(x,y,z) x ## y ## z
67 #define EVALUATOR3(x,y,z) PASTER3(x,y,z)
68 #define NVIC_TIMx_IRQ EVALUATOR3(NVIC_TIM, SPEKTRUM_TIMER,_IRQ)
69 #define NVIC_TIMx_DAC_IRQ EVALUATOR3(NVIC_TIM, SPEKTRUM_TIMER,_DAC_IRQ) // not really necessary, only for f4 which probably always has a timer 4
70 #define TIMx_ISR EVALUATOR3(tim, SPEKTRUM_TIMER,_isr)
71 #define TIMx_DAC_ISR EVALUATOR3(tim, SPEKTRUM_TIMER,_dac_isr)
73 #define PASTER2(x,y) x ## y
74 #define EVALUATOR2(x,y) PASTER2(x,y)
75 #define TIMx EVALUATOR2(TIM, SPEKTRUM_TIMER)
76 #define RCC_TIMx EVALUATOR2(RCC_TIM, SPEKTRUM_TIMER)
78 #ifndef SPEKTRUM_TIMER
79 #define SPEKTRUM_TIMER 6
82 #if (SPEKTRUM_TIMER == 6)
83 #ifndef NVIC_TIM6_IRQ_PRIO
84 #define NVIC_TIM6_IRQ_PRIO 2
85 #define NVIC_TIMx_IRQ_PRIO 2
87 #define NVIC_TIMx_IRQ_PRIO NVIC_TIM6_IRQ_PRIO
89 #ifndef NVIC_TIM6_DAC_IRQ_PRIO
90 #define NVIC_TIM6_DAC_IRQ_PRIO 2
91 #define NVIC_TIMx_DAC_IRQ_PRIO 2
93 #define NVIC_TIMx_DAC_IRQ_PRIO NVIC_TIM6_DAC_IRQ_PRIO
97 #if (SPEKTRUM_TIMER == 3)
98 #ifndef NVIC_TIM3_IRQ_PRIO
99 #define NVIC_TIM3_IRQ_PRIO 2
100 #define NVIC_TIMx_IRQ_PRIO 2
102 #define NVIC_TIMx_IRQ_PRIO NVIC_TIM6_IRQ_PRIO
104 #ifndef NVIC_TIM3_DAC_IRQ_PRIO
105 #define NVIC_TIM3_DAC_IRQ_PRIO 2
106 #define NVIC_TIMx_DAC_IRQ_PRIO 2
108 #define NVIC_TIMx_DAC_IRQ_PRIO NVIC_TIM6_DAC_IRQ_PRIO
114 #ifdef NVIC_UART_IRQ_PRIO
115 #define NVIC_PRIMARY_UART_PRIO NVIC_UART_IRQ_PRIO
117 #define NVIC_PRIMARY_UART_PRIO 2
127 #define __PrimaryUart(dev, _x) dev##_x
128 #define _PrimaryUart(dev, _x) __PrimaryUart(dev, _x)
129 #define PrimaryUart(_x) _PrimaryUart(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT, _x)
131 #define __SecondaryUart(dev, _x) dev##_x
132 #define _SecondaryUart(dev, _x) __SecondaryUart(dev, _x)
133 #define SecondaryUart(_x) _SecondaryUart(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT, _x)
151 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT)
153 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
155 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT)
197 #ifndef RC_SET_POLARITY
198 #define RC_SET_POLARITY gpio_clear
209 PrimarySpektrumState.
ReSync = 1;
211 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
212 SecondarySpektrumState.ReSync = 1;
216 #ifdef RC_POLARITY_GPIO_PORT
340 static uint8_t TmpExpFrames = 0;
347 if ((spektrum_state->
ReSync == 1) ||
348 ((spektrum_state->
Sync == 0) && (!TimedOut))) {
350 spektrum_state->
ReSync = 0;
352 spektrum_state->
Sync = 0;
363 if (spektrum_state->
Sync == 0) {
365 if (secondary_receiver) {
368 spektrum_state->
Sync = 1;
377 spektrum_state->
ReSync = 1;
385 if (spektrum_state->
Sync == 1) {
386 if (secondary_receiver) {
392 TmpEncType = (_c & 0x10) >> 4;
393 TmpExpFrames = _c & 0x03;
396 spektrum_state->
Sync = 2;
404 if (spektrum_state->
Sync == 2) {
409 spektrum_state->
Sync = 3;
415 if (spektrum_state->
Sync == 3) {
416 spektrum_state->
Sync = 2;
422 + (spektrum_state->
SecondFrame * 7)] = ChannelData;
430 if (spektrum_state->
FrameCnt == TmpExpFrames) {
435 if (!secondary_receiver) {
436 EncodingType = TmpEncType;
437 ExpectedFrames = TmpExpFrames;
439 spektrum_state->
Sync = 0;
460 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
464 (SecondarySpektrumState.RcAvailable)) {
468 (SecondarySpektrumState.RcAvailable)) {
470 <= SecondarySpektrumState.LostFrameCnt) ? 0 : 1;
473 BestReceiver = (PrimarySpektrumState.
RcAvailable) ? 0 : 1;
477 SecondarySpektrumState.RcAvailable = 0;
487 #ifndef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
488 ChannelData = PrimarySpektrumState.
values[i];
490 ChannelData = (!BestReceiver) ? PrimarySpektrumState.
values[i] :
491 SecondarySpektrumState.values[i];
496 switch (EncodingType) {
498 ChannelNum = (ChannelData >> 10) & 0x0f;
501 SpektrumBuf[ChannelNum] = ChannelData & 0x3ff;
502 SpektrumBuf[ChannelNum] -= 0x200;
503 SpektrumBuf[ChannelNum] *=
MAX_PPRZ / 0x156;
509 ChannelNum = (ChannelData >> 11) & 0x0f;
512 SpektrumBuf[ChannelNum] = ChannelData & 0x7ff;
513 SpektrumBuf[ChannelNum] -= 0x400;
514 SpektrumBuf[ChannelNum] *=
MAX_PPRZ / 0x2AC;
519 default : ChannelNum = 0x0F;
break;
522 if ((ChannelNum != 0x0F) && (ChannelNum > MaxChannelNum)) {
523 MaxChannelNum = ChannelNum;
529 if (ChannelCnt >= (MaxChannelNum + 1)) {
566 timer_set_mode(
TIMx, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
571 timer_set_prescaler(
TIMx, ((TIMx_clk /
ONE_MHZ) - 1));
577 #elif defined STM32F4
584 timer_enable_irq(
TIMx, TIM_DIER_UIE);
588 timer_enable_counter(
TIMx);
599 #elif defined STM32F4
608 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
609 if (SecondarySpektrumState.SpektrumTimer) {
610 --SecondarySpektrumState.SpektrumTimer;
636 usart_set_stopbits(
PrimaryUart(_DEV), USART_STOPBITS_1);
637 usart_set_parity(
PrimaryUart(_DEV), USART_PARITY_NONE);
638 usart_set_flow_control(
PrimaryUart(_DEV), USART_FLOWCONTROL_NONE);
647 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
665 usart_set_flow_control(
SecondaryUart(_DEV), USART_FLOWCONTROL_NONE);
685 if (((USART_CR1(
PrimaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
686 ((USART_SR(
PrimaryUart(_DEV)) & USART_SR_TXE) != 0)) {
690 if (((USART_CR1(
PrimaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
691 ((USART_SR(
PrimaryUart(_DEV)) & USART_SR_RXNE) != 0)) {
704 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
707 if (((USART_CR1(
SecondaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
712 if (((USART_CR1(
SecondaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
731 #ifndef SPEKTRUM_PRIMARY_BIND_CONF_PORT
732 #define SPEKTRUM_PRIMARY_BIND_CONF_PORT PrimaryUart(_BANK)
734 #ifndef SPEKTRUM_PRIMARY_BIND_CONF_PIN
735 #define SPEKTRUM_PRIMARY_BIND_CONF_PIN PrimaryUart(_PIN)
737 #ifndef SPEKTRUM_SECONDARY_BIND_CONF_PORT
738 #define SPEKTRUM_SECONDARY_BIND_CONF_PORT SecondaryUart(_BANK)
740 #ifndef SPEKTRUM_SECONDARY_BIND_CONF_PIN
741 #define SPEKTRUM_SECONDARY_BIND_CONF_PIN SecondaryUart(_PIN)
753 #ifdef SPEKTRUM_BIND_PIN_PORT
754 #ifdef SPEKTRUM_BIND_PIN_HIGH
788 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
807 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
818 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
void gpio_setup_pin_af(ioportid_t port, uint16_t pin, uint8_t af, bool is_output)
Setup a gpio for input or output with alternate function.
int16_t SpektrumBuf[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]
void radio_control_impl_init(void)
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
#define SPEKTRUM_PRIMARY_BIND_CONF_PIN
#define SPEKTRUM_SECONDARY_BIND_CONF_PIN
#define RC_POLARITY_GPIO_PORT
#define SLAVE_RECEIVER_PULSES
#define NVIC_TIMx_IRQ_PRIO
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
#define SPEKTRUM_SECONDARY_BIND_CONF_PORT
Some architecture independent helper functions for GPIOs.
void PrimaryUart() _ISR(void)
void SpektrumTimerInit(void)
#define MAX_SPEKTRUM_FRAMES
#define MASTER_RECEIVER_PULSES
#define SPEKTRUM_BIND_PIN
uint32_t timer_get_frequency(uint32_t timer_peripheral)
Get Timer clock frequency (before prescaling) Only valid if using the internal clock for the timer...
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
static uint8_t ExpectedFrames
#define SecondaryUart(_x)
#define RC_POLARITY_GPIO_PIN
void gpio_setup_input_pullup(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs with pull up resistor enabled.
timer_clear_flag(TIMx, TIM_SR_UIF)
void gpio_enable_clock(uint32_t port)
Enable the relevant clock.
void sys_time_usleep(uint32_t us)
sys_time_usleep(uint32_t us)
Architecture independent timing functions.
SpektrumStateType PrimarySpektrumState
#define SPEKTRUM_CHANNELS_PER_FRAME
#define SPEKTRUM_NB_CHANNEL
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
static uint8_t EncodingType
#define NVIC_PRIMARY_UART_PRIO
struct RadioControl radio_control
#define NVIC_TIMx_DAC_IRQ
#define RC_SET_POLARITY
Set polarity using RC_POLARITY_GPIO.
#define RADIO_CONTROL_NB_CHANNEL
#define SPEKTRUM_BIND_PIN_PORT
#define TIM_TICS_FOR_100us
#define SPEKTRUM_PRIMARY_BIND_CONF_PORT
static uint8_t gpio_get(ioportid_t port, uint16_t pin)
Get level of a gpio.
#define RADIO_CONTROL_SPEKTRUM_SIGNS
void RadioControlEventImp(void(*frame_handler)(void))
void SpektrumUartInit(void)
void radio_control_spektrum_try_bind(void)
void gpio_setup_input_pulldown(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs with pull down resistors enabled.
uint8_t time_since_last_frame
#define NVIC_TIMx_DAC_IRQ_PRIO
void gpio_setup_input(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs.
static void SpektrumParser(uint8_t _c, SpektrumStateType *spektrum_state, bool secondary_receiver)
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
int16_t values[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]