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
52 #define MASTER_RECEIVER_PULSES 5
53 #define SLAVE_RECEIVER_PULSES 6
55 #define TIM_TICS_FOR_100us 100
56 #define MIN_FRAME_SPACE 70 // 7ms
57 #define MAX_BYTE_SPACE 3 // .3ms
59 #ifndef NVIC_TIM6_IRQ_PRIO
60 #define NVIC_TIM6_IRQ_PRIO 2
63 #ifndef NVIC_TIM6_DAC_IRQ_PRIO
64 #define NVIC_TIM6_DAC_IRQ_PRIO 2
68 #ifdef NVIC_UART_IRQ_PRIO
69 #define NVIC_PRIMARY_UART_PRIO NVIC_UART_IRQ_PRIO
71 #define NVIC_PRIMARY_UART_PRIO 2
81 #define __PrimaryUart(dev, _x) dev##_x
82 #define _PrimaryUart(dev, _x) __PrimaryUart(dev, _x)
83 #define PrimaryUart(_x) _PrimaryUart(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT, _x)
85 #define __SecondaryUart(dev, _x) dev##_x
86 #define _SecondaryUart(dev, _x) __SecondaryUart(dev, _x)
87 #define SecondaryUart(_x) _SecondaryUart(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT, _x)
105 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT)
107 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
109 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT)
154 #ifndef RC_SET_POLARITY
155 #define RC_SET_POLARITY gpio_clear
166 PrimarySpektrumState.
ReSync = 1;
168 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
169 SecondarySpektrumState.ReSync = 1;
173 #ifdef RC_POLARITY_GPIO_PORT
295 static uint8_t TmpExpFrames = 0;
302 if ((spektrum_state->
ReSync == 1) ||
303 ((spektrum_state->
Sync == 0) && (!TimedOut))) {
305 spektrum_state->
ReSync = 0;
307 spektrum_state->
Sync = 0;
317 if (spektrum_state->
Sync == 0) {
319 if (secondary_receiver) {
322 spektrum_state->
Sync = 1;
331 spektrum_state->
ReSync = 1;
339 if (spektrum_state->
Sync == 1) {
340 if (secondary_receiver) {
346 TmpEncType = (_c & 0x10) >> 4;
347 TmpExpFrames = _c & 0x03;
350 spektrum_state->
Sync = 2;
358 if (spektrum_state->
Sync == 2) {
363 spektrum_state->
Sync = 3;
369 if (spektrum_state->
Sync == 3) {
370 spektrum_state->
Sync = 2;
376 + (spektrum_state->
SecondFrame * 7)] = ChannelData;
384 if (spektrum_state->
FrameCnt == TmpExpFrames) {
389 if (!secondary_receiver) {
390 EncodingType = TmpEncType;
391 ExpectedFrames = TmpExpFrames;
393 spektrum_state->
Sync = 0;
414 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
418 (SecondarySpektrumState.RcAvailable)) {
422 (SecondarySpektrumState.RcAvailable)) {
424 <= SecondarySpektrumState.LostFrameCnt) ? 0 : 1;
427 BestReceiver = (PrimarySpektrumState.
RcAvailable) ? 0 : 1;
431 SecondarySpektrumState.RcAvailable = 0;
441 #ifndef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
442 ChannelData = PrimarySpektrumState.
values[i];
444 ChannelData = (!BestReceiver) ? PrimarySpektrumState.
values[i] :
445 SecondarySpektrumState.values[i];
450 switch (EncodingType) {
452 ChannelNum = (ChannelData >> 10) & 0x0f;
455 SpektrumBuf[ChannelNum] = ChannelData & 0x3ff;
456 SpektrumBuf[ChannelNum] -= 0x200;
457 SpektrumBuf[ChannelNum] *=
MAX_PPRZ / 0x156;
463 ChannelNum = (ChannelData >> 11) & 0x0f;
466 SpektrumBuf[ChannelNum] = ChannelData & 0x7ff;
467 SpektrumBuf[ChannelNum] -= 0x400;
468 SpektrumBuf[ChannelNum] *=
MAX_PPRZ / 0x2AC;
473 default : ChannelNum = 0x0F;
break;
476 if ((ChannelNum != 0x0F) && (ChannelNum > MaxChannelNum)) {
477 MaxChannelNum = ChannelNum;
483 if (ChannelCnt >= (MaxChannelNum + 1)) {
514 rcc_periph_clock_enable(RCC_TIM6);
517 timer_set_mode(TIM6, TIM_CR1_CKD_CK_INT, 0, 0);
522 timer_set_prescaler(TIM6, ((tim6_clk /
ONE_MHZ) - 1));
527 nvic_enable_irq(NVIC_TIM6_IRQ);
528 #elif defined STM32F4
535 timer_enable_irq(TIM6, TIM_DIER_UIE);
539 timer_enable_counter(TIM6);
550 #elif defined STM32F4
559 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
560 if (SecondarySpektrumState.SpektrumTimer) {
561 --SecondarySpektrumState.SpektrumTimer;
587 usart_set_stopbits(
PrimaryUart(_DEV), USART_STOPBITS_1);
588 usart_set_parity(
PrimaryUart(_DEV), USART_PARITY_NONE);
589 usart_set_flow_control(
PrimaryUart(_DEV), USART_FLOWCONTROL_NONE);
598 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
616 usart_set_flow_control(
SecondaryUart(_DEV), USART_FLOWCONTROL_NONE);
636 if (((USART_CR1(
PrimaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
637 ((USART_SR(
PrimaryUart(_DEV)) & USART_SR_TXE) != 0)) {
641 if (((USART_CR1(
PrimaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
642 ((USART_SR(
PrimaryUart(_DEV)) & USART_SR_RXNE) != 0)) {
655 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
658 if (((USART_CR1(
SecondaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
663 if (((USART_CR1(
SecondaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
682 #ifndef SPEKTRUM_PRIMARY_BIND_CONF_PORT
683 #define SPEKTRUM_PRIMARY_BIND_CONF_PORT PrimaryUart(_BANK)
685 #ifndef SPEKTRUM_PRIMARY_BIND_CONF_PIN
686 #define SPEKTRUM_PRIMARY_BIND_CONF_PIN PrimaryUart(_PIN)
688 #ifndef SPEKTRUM_SECONDARY_BIND_CONF_PORT
689 #define SPEKTRUM_SECONDARY_BIND_CONF_PORT SecondaryUart(_BANK)
691 #ifndef SPEKTRUM_SECONDARY_BIND_CONF_PIN
692 #define SPEKTRUM_SECONDARY_BIND_CONF_PIN SecondaryUart(_PIN)
705 #ifdef SPEKTRUM_BIND_PIN_HIGH
738 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
757 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
768 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
int16_t SpektrumBuf[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]
void radio_control_impl_init(void)
void gpio_setup_input_pulldown(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs with pull down resistors enabled.
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
#define SPEKTRUM_PRIMARY_BIND_CONF_PIN
timer_clear_flag(TIM6, TIM_SR_UIF)
#define SPEKTRUM_SECONDARY_BIND_CONF_PIN
#define SLAVE_RECEIVER_PULSES
#define RC_POLARITY_GPIO_PIN
#define NVIC_TIM6_DAC_IRQ
CM3_WEAK tim6_dac_isr(void)
#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
#define NVIC_TIM6_IRQ_PRIO
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]
static uint8_t ExpectedFrames
#define SecondaryUart(_x)
void gpio_set(uint32_t port, uint16_t pin)
Set a gpio output to high level.
void tim6_irq_handler(void)
Architecture independent timing functions.
SpektrumStateType PrimarySpektrumState
#define RC_POLARITY_GPIO_PORT
#define SPEKTRUM_CHANNELS_PER_FRAME
#define SPEKTRUM_NB_CHANNEL
void gpio_clear(uint32_t port, uint16_t pin)
Clear a gpio output to low level.
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
static uint8_t EncodingType
#define NVIC_PRIMARY_UART_PRIO
struct RadioControl radio_control
#define RC_SET_POLARITY
Set polarity using RC_POLARITY_GPIO.
#define RADIO_CONTROL_NB_CHANNEL
#define SPEKTRUM_BIND_PIN_PORT
void gpio_setup_pin_af(uint32_t port, uint16_t pin, uint8_t af, bool_t is_output)
Setup a gpio for input or output with alternate function.
void gpio_setup_input_pullup(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs with pull up resistor enabled.
#define TIM_TICS_FOR_100us
static void sys_time_usleep(uint32_t us)
#define SPEKTRUM_PRIMARY_BIND_CONF_PORT
#define RADIO_CONTROL_SPEKTRUM_SIGNS
void RadioControlEventImp(void(*frame_handler)(void))
void SpektrumUartInit(void)
#define NVIC_TIM6_DAC_IRQ_PRIO
void radio_control_spektrum_try_bind(void)
uint16_t gpio_get(uint32_t gpioport, uint16_t gpios)
Read a gpio value.
void gpio_setup_input(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs.
uint8_t time_since_last_frame
void gpio_enable_clock(uint32_t port)
Enable the relevant clock.
void gpio_setup_output(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
static void SpektrumParser(uint8_t _c, SpektrumStateType *spektrum_state, bool_t secondary_receiver)
int16_t values[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]