diff --git a/conf/airframes/ENAC/fixed-wing/chimera.xml b/conf/airframes/ENAC/fixed-wing/chimera.xml index 233e1c30446..cfb9bd01249 100644 --- a/conf/airframes/ENAC/fixed-wing/chimera.xml +++ b/conf/airframes/ENAC/fixed-wing/chimera.xml @@ -18,7 +18,7 @@ UBX GPS / HMC58XX mag (drotek) - + diff --git a/conf/modules/radio_control_spektrum.xml b/conf/modules/radio_control_spektrum.xml index 28b2367064e..2256f3b7ce0 100644 --- a/conf/modules/radio_control_spektrum.xml +++ b/conf/modules/radio_control_spektrum.xml @@ -8,50 +8,70 @@ Define USE_DSMX on STM32 microcontrollers to bind in DSMX instead of DSM2 - - + + -
- + - - - ifeq ($(ARCH), lpc21) - ifndef RADIO_CONTROL_SPEKTRUM_MODEL - RADIO_CONTROL_SPEKTRUM_MODEL=\"subsystems/radio_control/spektrum_dx7se.h\" - endif - RC_CFLAGS += -DRADIO_CONTROL_SPEKTRUM_MODEL_H=$(RADIO_CONTROL_SPEKTRUM_MODEL) - endif - - - + - - - - - + + + + + + + + + + + + + + + + + + - + + + - - - - - - + + + + + + + + + + + + + + + + + - + + + + + + diff --git a/sw/airborne/arch/chibios/mcu_periph/sys_time_arch.c b/sw/airborne/arch/chibios/mcu_periph/sys_time_arch.c index f99391d5824..5b17afa9320 100644 --- a/sw/airborne/arch/chibios/mcu_periph/sys_time_arch.c +++ b/sw/airborne/arch/chibios/mcu_periph/sys_time_arch.c @@ -94,8 +94,15 @@ uint32_t get_sys_time_msec(void) */ void sys_time_usleep(uint32_t us) { - uint64_t wait_st = ((uint64_t)us * CH_CFG_ST_FREQUENCY) / 1000000UL; - chThdSleep((systime_t)wait_st); + if (us < 1000) { + // for small time, use the polled version instead of thread sleep + chSysDisable(); + chSysPolledDelayX(US2RTC(STM32_HCLK, us)); + chSysEnable(); + } else { + uint64_t wait_st = ((uint64_t)us * CH_CFG_ST_FREQUENCY) / 1000000UL; + chThdSleep((systime_t)wait_st); + } } void sys_time_msleep(uint16_t ms) diff --git a/sw/airborne/arch/lpc21/subsystems/radio_control/spektrum_arch.c b/sw/airborne/arch/lpc21/subsystems/radio_control/spektrum_arch.c deleted file mode 100644 index 5a49f7303cb..00000000000 --- a/sw/airborne/arch/lpc21/subsystems/radio_control/spektrum_arch.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2008-2009 Antoine Drouin - * - * This file is part of paparazzi. - * - * paparazzi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * paparazzi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "subsystems/radio_control.h" -#include "subsystems/radio_control/spektrum_arch.h" - -bool rc_spk_parser_status; -uint8_t rc_spk_parser_idx; -uint8_t rc_spk_parser_buf[RADIO_CONTROL_NB_CHANNEL * 2]; -const int16_t rc_spk_throw[RADIO_CONTROL_NB_CHANNEL] = RC_SPK_THROWS; - -void radio_control_impl_init(void) -{ - rc_spk_parser_status = RC_SPK_STA_UNINIT; - rc_spk_parser_idx = 0; -} diff --git a/sw/airborne/arch/lpc21/subsystems/radio_control/spektrum_arch.h b/sw/airborne/arch/lpc21/subsystems/radio_control/spektrum_arch.h deleted file mode 100644 index f3f9c7cf85a..00000000000 --- a/sw/airborne/arch/lpc21/subsystems/radio_control/spektrum_arch.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2009-2010 The Paparazzi Team - * - * This file is part of paparazzi. - * - * paparazzi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * paparazzi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef RADIO_CONTROL_SPEKTRUM_ARCH_H -#define RADIO_CONTROL_SPEKTRUM_ARCH_H - -#include "std.h" -#include "mcu_periph/uart.h" - -#include RADIO_CONTROL_SPEKTRUM_MODEL_H - -#define RC_SPK_SYNC_1 0x03 - -#define RC_SPK_STA_UNINIT 0 -#define RC_SPK_STA_GOT_SYNC_1 1 -#define RC_SPK_STA_GOT_SYNC_2 2 - -extern bool rc_spk_parser_status; -extern uint8_t rc_spk_parser_idx; -extern uint8_t rc_spk_parser_buf[RADIO_CONTROL_NB_CHANNEL * 2]; - -#define MAX_SPK 344 - - -extern const int16_t rc_spk_throw[RADIO_CONTROL_NB_CHANNEL]; - -#define __RcLink(dev, _x) dev##_x -#define _RcLink(dev, _x) __RcLink(dev, _x) -#define RcLink(_x) _RcLink(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT, _x) - -#define RcLinkChAvailable() RcLink(ChAvailable()) -#define RcLinkGetCh() RcLink(Getch()) - -#define RadioControlEventImpl(_received_frame_handler) { \ - while (RcLinkChAvailable()) { \ - int8_t c = RcLinkGetCh(); \ - switch (rc_spk_parser_status) { \ - case RC_SPK_STA_UNINIT: \ - if (c==RC_SPK_SYNC_1) \ - rc_spk_parser_status = RC_SPK_STA_GOT_SYNC_1; \ - break; \ - case RC_SPK_STA_GOT_SYNC_1: \ - if (c==RC_SPK_SYNC_2) { \ - rc_spk_parser_status = RC_SPK_STA_GOT_SYNC_2; \ - rc_spk_parser_idx = 0; \ - } \ - else \ - rc_spk_parser_status = RC_SPK_STA_UNINIT; \ - break; \ - case RC_SPK_STA_GOT_SYNC_2: \ - rc_spk_parser_buf[rc_spk_parser_idx] = c; \ - rc_spk_parser_idx++; \ - if (rc_spk_parser_idx >= 2*RADIO_CONTROL_NB_CHANNEL) { \ - rc_spk_parser_status = RC_SPK_STA_UNINIT; \ - radio_control.frame_cpt++; \ - radio_control.time_since_last_frame = 0; \ - radio_control.status = RC_OK; \ - uint8_t i; \ - for (i=0;i> 10;*/ \ - const int16_t val = (tmp&0x03FF) - 512; \ - radio_control.values[i] = val; \ - radio_control.values[i] *= rc_spk_throw[i]; \ - if (i==RADIO_CONTROL_THROTTLE) { \ - radio_control.values[i] += MAX_PPRZ; \ - radio_control.values[i] /= 2; \ - } \ - } \ - _received_frame_handler(); \ - } \ - break; \ - default: \ - rc_spk_parser_status = RC_SPK_STA_UNINIT; \ - } \ - } \ - } - - -#endif /* RADIO_CONTROL_SPEKTRUM_ARCH_H */ diff --git a/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.c b/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.c index 3480ecd2b3e..182a7d0df86 100644 --- a/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.c +++ b/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.c @@ -27,7 +27,7 @@ */ #include "subsystems/radio_control.h" -#include "subsystems/radio_control/spektrum.h" +#include "subsystems/radio_control/spektrum_arch.h" #include "std.h" #include @@ -39,13 +39,11 @@ static bool spektrum_available; -void radio_control_spektrum_try_bind(void) {} - void radio_control_impl_init(void) { spektrum_available = false; } -void RadioControlEventImp(void (*frame_handler)(void)) +void spektrum_event(void (*frame_handler)(void)) { if (spektrum_available) { radio_control.frame_cpt++; @@ -56,6 +54,8 @@ void RadioControlEventImp(void (*frame_handler)(void)) spektrum_available = false; } +void spektrum_try_bind(void) {} + #if USE_NPS #ifdef RADIO_CONTROL void radio_control_feed(void) diff --git a/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.h b/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.h index 94239f7db97..ffdc9f964a1 100644 --- a/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.h +++ b/sw/airborne/arch/sim/subsystems/radio_control/spektrum_arch.h @@ -23,43 +23,11 @@ #ifndef RADIO_CONTROL_SPEKTRUM_ARCH_H #define RADIO_CONTROL_SPEKTRUM_ARCH_H +#include "subsystems/radio_control/spektrum_radio.h" -/* - * All Spektrum and JR 2.4 GHz transmitters - * have the same channel assignments. - */ - - -#ifndef RADIO_CONTROL_NB_CHANNEL -#define RADIO_CONTROL_NB_CHANNEL 12 -#endif - -#if RADIO_CONTROL_NB_CHANNEL > 12 -#error "RADIO_CONTROL_NB_CHANNEL mustn't be higher than 12." -#endif - -/* channel assignments */ -#define RADIO_THROTTLE 0 -#define RADIO_ROLL 1 -#define RADIO_PITCH 2 -#define RADIO_YAW 3 -#define RADIO_GEAR 4 -#define RADIO_FLAP 5 -#define RADIO_AUX1 5 -#define RADIO_AUX2 6 -#define RADIO_AUX3 7 -#define RADIO_AUX4 8 -#define RADIO_AUX5 9 -#define RADIO_AUX6 10 -#define RADIO_AUX7 11 - -/* really for a 9 channel transmitter - we would swap the order of these */ -#ifndef RADIO_MODE -#define RADIO_MODE RADIO_GEAR -#endif - -extern void RadioControlEventImp(void (*_received_frame_handler)(void)); +extern void spektrum_event(void (*_received_frame_handler)(void)); +#define RadioControlEventImp spektrum_event +extern void spektrum_try_bind(void); #if USE_NPS extern void radio_control_feed(void); diff --git a/sw/airborne/arch/stm32/subsystems/radio_control/spektrum_arch.c b/sw/airborne/arch/stm32/subsystems/radio_control/spektrum_arch.c deleted file mode 100644 index f6d765d3464..00000000000 --- a/sw/airborne/arch/stm32/subsystems/radio_control/spektrum_arch.c +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (C) 2010 Eric Parsonage - * - * This file is part of paparazzi. - * - * paparazzi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * paparazzi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include - -#include "subsystems/radio_control.h" -#include "subsystems/radio_control/spektrum_arch.h" -#include "mcu_periph/uart.h" -#include "mcu_periph/gpio.h" -#include "mcu_periph/sys_time.h" - -// for timer_get_frequency -#include "mcu_arch.h" - -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") - -// for Min macro -#include "std.h" - -#include BOARD_CONFIG - -#define SPEKTRUM_CHANNELS_PER_FRAME 7 -#define MAX_SPEKTRUM_FRAMES 2 -#define MAX_SPEKTRUM_CHANNELS 16 - -#define ONE_MHZ 1000000 - -/* Number of low pulses sent to satellite receivers */ -#if USE_DSMX -#define MASTER_RECEIVER_PULSES 9 -#define SLAVE_RECEIVER_PULSES 10 -#else -#define MASTER_RECEIVER_PULSES 5 -#define SLAVE_RECEIVER_PULSES 6 -#endif - -#define TIM_TICS_FOR_100us 100 -#define MIN_FRAME_SPACE 70 // 7ms -#define MAX_BYTE_SPACE 3 // .3ms - - -//not all f1's have a timer 6, so, some redefines have to happen -#define PASTER3(x,y,z) x ## y ## z -#define EVALUATOR3(x,y,z) PASTER3(x,y,z) -#define NVIC_TIMx_IRQ EVALUATOR3(NVIC_TIM, SPEKTRUM_TIMER,_IRQ) -#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 -#define TIMx_ISR EVALUATOR3(tim, SPEKTRUM_TIMER,_isr) -#define TIMx_DAC_ISR EVALUATOR3(tim, SPEKTRUM_TIMER,_dac_isr) - -#define PASTER2(x,y) x ## y -#define EVALUATOR2(x,y) PASTER2(x,y) -#define TIMx EVALUATOR2(TIM, SPEKTRUM_TIMER) -#define RCC_TIMx EVALUATOR2(RCC_TIM, SPEKTRUM_TIMER) - -#ifndef SPEKTRUM_TIMER -#define SPEKTRUM_TIMER 6 -#endif - -#if (SPEKTRUM_TIMER == 6) -#ifndef NVIC_TIM6_IRQ_PRIO -#define NVIC_TIM6_IRQ_PRIO 2 -#define NVIC_TIMx_IRQ_PRIO 2 -#else -#define NVIC_TIMx_IRQ_PRIO NVIC_TIM6_IRQ_PRIO -#endif -#ifndef NVIC_TIM6_DAC_IRQ_PRIO -#define NVIC_TIM6_DAC_IRQ_PRIO 2 -#define NVIC_TIMx_DAC_IRQ_PRIO 2 -#else -#define NVIC_TIMx_DAC_IRQ_PRIO NVIC_TIM6_DAC_IRQ_PRIO -#endif -#endif - -#if (SPEKTRUM_TIMER == 3) -#ifndef NVIC_TIM3_IRQ_PRIO -#define NVIC_TIM3_IRQ_PRIO 2 -#define NVIC_TIMx_IRQ_PRIO 2 -#else -#define NVIC_TIMx_IRQ_PRIO NVIC_TIM6_IRQ_PRIO -#endif -#ifndef NVIC_TIM3_DAC_IRQ_PRIO -#define NVIC_TIM3_DAC_IRQ_PRIO 2 -#define NVIC_TIMx_DAC_IRQ_PRIO 2 -#else -#define NVIC_TIMx_DAC_IRQ_PRIO NVIC_TIM6_DAC_IRQ_PRIO -#endif -#endif - -PRINT_CONFIG_MSG_VALUE("SPEKTRUM_TIMER: " , SPEKTRUM_TIMER) - -#ifdef NVIC_UART_IRQ_PRIO -#define NVIC_PRIMARY_UART_PRIO NVIC_UART_IRQ_PRIO -#else -#define NVIC_PRIMARY_UART_PRIO 2 -#endif - -/* - * in the makefile we set RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT to be UARTx - * but in uart_hw.c the initialisation functions are - * defined as uartx these macros give us the glue - * that allows static calls at compile time - */ - -#define __PrimaryUart(dev, _x) dev##_x -#define _PrimaryUart(dev, _x) __PrimaryUart(dev, _x) -#define PrimaryUart(_x) _PrimaryUart(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT, _x) - -#define __SecondaryUart(dev, _x) dev##_x -#define _SecondaryUart(dev, _x) __SecondaryUart(dev, _x) -#define SecondaryUart(_x) _SecondaryUart(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT, _x) - -struct SpektrumStateStruct { - uint8_t ReSync; - uint8_t SpektrumTimer; - uint8_t Sync; - uint8_t ChannelCnt; - uint8_t FrameCnt; - uint8_t HighByte; - uint8_t SecondFrame; - uint16_t LostFrameCnt; - uint8_t RcAvailable; - int16_t values[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]; -}; - -typedef struct SpektrumStateStruct SpektrumStateType; - -SpektrumStateType PrimarySpektrumState = {1, 0, 0, 0, 0, 0, 0, 0, 0, {0}}; -PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT) - -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT -PRINT_CONFIG_MSG("Using secondary spektrum receiver.") -PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT) -SpektrumStateType SecondarySpektrumState = {1, 0, 0, 0, 0, 0, 0, 0, 0, {0}}; -#else -PRINT_CONFIG_MSG("NOT using secondary spektrum receiver.") -#endif - -int16_t SpektrumBuf[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]; -/* the order of the channels on a spektrum is always as follows : - * - * Throttle 0 - * Aileron 1 - * Elevator 2 - * Rudder 3 - * Gear 4 - * Flap/Aux1 5 - * Aux2 6 - * Aux3 7 - * Aux4 8 - * Aux5 9 - * Aux6 10 - * Aux7 11 - */ - -/* reverse some channels to suit Paparazzi conventions */ -/* the maximum number of channels a Spektrum can transmit is 12 */ -int8_t SpektrumSigns[] = RADIO_CONTROL_SPEKTRUM_SIGNS; - -/* Parser state variables */ -static uint8_t EncodingType = 0; -static uint8_t ExpectedFrames = 0; - -/* initialise the timer used by the parser to ensure sync */ -void SpektrumTimerInit(void); - -/** Set polarity using RC_POLARITY_GPIO. - * SBUS signal has a reversed polarity compared to normal UART - * this allows to using hardware UART peripheral by changing - * the input signal polarity. - * Setting this gpio ouput high inverts the signal, - * output low sets it to normal polarity. - * So for spektrum this is set to normal polarity. - */ -#ifndef RC_SET_POLARITY -#define RC_SET_POLARITY gpio_clear -#endif - -/***************************************************************************** -* -* Initialise the timer an uarts used by the Spektrum receiver subsystem -* -*****************************************************************************/ -void radio_control_impl_init(void) -{ - - PrimarySpektrumState.ReSync = 1; - -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - SecondarySpektrumState.ReSync = 1; -#endif - - // Set polarity to normal on boards that can change this -#ifdef RC_POLARITY_GPIO_PORT - gpio_setup_output(RC_POLARITY_GPIO_PORT, RC_POLARITY_GPIO_PIN); - RC_SET_POLARITY(RC_POLARITY_GPIO_PORT, RC_POLARITY_GPIO_PIN); -#endif - - SpektrumTimerInit(); - SpektrumUartInit(); -} - -/***************************************************************************** - * The bind function means that the satellite receivers believe they are - * connected to a 9 channel JR-R921 24 receiver thus during the bind process - * they try to get the transmitter to transmit at the highest resolution that - * it can manage. The data is contained in 16 byte packets transmitted at - * 115200 baud. Depending on the transmitter either 1 or 2 frames are required - * to contain the data for all channels. These frames are either 11ms or 22ms - * apart. - * - * The format of each frame for the main receiver is as follows - * - * byte1: frame loss data - * byte2: transmitter information - * byte3: and byte4: channel data - * byte5: and byte6: channel data - * byte7: and byte8: channel data - * byte9: and byte10: channel data - * byte11: and byte12: channel data - * byte13: and byte14: channel data - * byte15: and byte16: channel data - * - * - * The format of each frame for the secondary receiver is as follows - * - * byte1: frame loss data - * byte2: frame loss data - * byte3: and byte4: channel data - * byte5: and byte6: channel data - * byte7: and byte8: channel data - * byte9: and byte10: channel data - * byte11: and byte12: channel data - * byte13: and byte14: channel data - * byte15: and byte16: channel data - * - * The frame loss data bytes starts out containing 0 as long as the - * transmitter is switched on before the receivers. It then increments - * whenever frames are dropped. - * - * Three values for the transmitter information byte have been seen thus far - * - * 0x01 From a Spektrum DX7eu which transmits a single frame containing all - * channel data every 22ms with 10bit resolution. - * - * 0x02 From a Spektrum DM9 module which transmits two frames to carry the - * data for all channels 11ms apart with 10bit resolution. - * - * 0x12 From a Spektrum DX7se which transmits two frames to carry the - * data for all channels 11ms apart with 11bit resolution. - * - * 0x12 From a JR X9503 which transmits two frames to carry the - * data for all channels 11ms apart with 11bit resolution. - * - * 0x01 From a Spektrum DX7 which transmits a single frame containing all - * channel data every 22ms with 10bit resolution. - * - * 0x12 From a JR DSX12 which transmits two frames to carry the - * data for all channels 11ms apart with 11bit resolution. - * - * 0x1 From a Spektru DX5e which transmits a single frame containing all - * channel data every 22ms with 10bit resolution. - * - * 0x01 From a Spektrum DX6i which transmits a single frame containing all - * channel data every 22ms with 10bit resolution. - * - * Currently the assumption is that the data has the form : - * - * [0 0 0 R 0 0 N1 N0] - * - * where : - * - * 0 means a '0' bit - * R: 0 for 10 bit resolution 1 for 11 bit resolution channel data - * N1 to N0 is the number of frames required to receive all channel - * data. - * - * Channels can have either 10bit or 11bit resolution. Data from a tranmitter - * with 10 bit resolution has the form: - * - * [F 0 C3 C2 C1 C0 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0] - * - * Data from a tranmitter with 11 bit resolution has the form - * - * [F C3 C2 C1 C0 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0] - * - * where : - * - * 0 means a '0' bit - * F: Normally 0 but set to 1 for the first channel of the 2nd frame if a - * second frame is transmitted. - * - * C3 to C0 is the channel number, 4 bit, matching the numbers allocated in - * the transmitter. - * - * D9 to D0 is the channel data (10 bit) 0xaa..0x200..0x356 for - * 100% transmitter-travel - * - * - * D10 to D0 is the channel data (11 bit) 0x154..0x400..0x6AC for - * 100% transmitter-travel - *****************************************************************************/ - -/***************************************************************************** -* -* Spektrum Parser captures frame data by using time between frames to sync on -* -*****************************************************************************/ - -static inline void SpektrumParser(uint8_t _c, SpektrumStateType *spektrum_state, bool secondary_receiver) -{ - - - - uint16_t ChannelData; - uint8_t TimedOut; - static uint8_t TmpEncType = 0; /* 0 = 10bit, 1 = 11 bit */ - static uint8_t TmpExpFrames = 0; /* # of frames for channel data */ - - TimedOut = (!spektrum_state->SpektrumTimer) ? 1 : 0; - - /* If we have just started the resync process or */ - /* if we have recieved a character before our */ - /* 7ms wait has finished */ - if ((spektrum_state->ReSync == 1) || - ((spektrum_state->Sync == 0) && (!TimedOut))) { - - spektrum_state->ReSync = 0; - spektrum_state->SpektrumTimer = MIN_FRAME_SPACE; - spektrum_state->Sync = 0; - spektrum_state->ChannelCnt = 0; - spektrum_state->FrameCnt = 0; - spektrum_state->SecondFrame = 0; - return; - } -//LED_OFF(1); - - /* the first byte of a new frame. It was received */ - /* more than 7ms after the last received byte. */ - /* It represents the number of lost frames so far.*/ - if (spektrum_state->Sync == 0) { - spektrum_state->LostFrameCnt = _c; - if (secondary_receiver) { /* secondary receiver */ - spektrum_state->LostFrameCnt = spektrum_state->LostFrameCnt << 8; - } - spektrum_state->Sync = 1; - spektrum_state->SpektrumTimer = MAX_BYTE_SPACE; - return; - } - - /* all other bytes should be recieved within */ - /* MAX_BYTE_SPACE time of the last byte received */ - /* otherwise something went wrong resynchronise */ - if (TimedOut) { - spektrum_state->ReSync = 1; - /* next frame not expected sooner than 7ms */ - spektrum_state->SpektrumTimer = MIN_FRAME_SPACE; - return; - } - - /* second character determines resolution and frame rate for main */ - /* receiver or low byte of LostFrameCount for secondary receiver */ - if (spektrum_state->Sync == 1) { - if (secondary_receiver) { - spektrum_state->LostFrameCnt += _c; - TmpExpFrames = ExpectedFrames; - } else { - /** @todo collect more data. I suspect that there is a low res */ - /* protocol that is still 10 bit but without using the full range. */ - TmpEncType = (_c & 0x10) >> 4; /* 0 = 10bit, 1 = 11 bit */ - TmpExpFrames = _c & 0x03; /* 1 = 1 frame contains all channels */ - /* 2 = 2 channel data in 2 frames */ - } - spektrum_state->Sync = 2; - spektrum_state->SpektrumTimer = MAX_BYTE_SPACE; - return; - } - - /* high byte of channel data if this is the first byte */ - /* of channel data and the most significant bit is set */ - /* then this is the second frame of channel data. */ - if (spektrum_state->Sync == 2) { - spektrum_state->HighByte = _c; - if (spektrum_state->ChannelCnt == 0) { - spektrum_state->SecondFrame = (spektrum_state->HighByte & 0x80) ? 1 : 0; - } - spektrum_state->Sync = 3; - spektrum_state->SpektrumTimer = MAX_BYTE_SPACE; - return; - } - - /* low byte of channel data */ - if (spektrum_state->Sync == 3) { - spektrum_state->Sync = 2; - spektrum_state->SpektrumTimer = MAX_BYTE_SPACE; - /* we overwrite the buffer now so rc data is not available now */ - spektrum_state->RcAvailable = 0; - ChannelData = ((uint16_t)spektrum_state->HighByte << 8) | _c; - spektrum_state->values[spektrum_state->ChannelCnt - + (spektrum_state->SecondFrame * 7)] = ChannelData; - spektrum_state->ChannelCnt ++; - } - - /* If we have a whole frame */ - if (spektrum_state->ChannelCnt >= SPEKTRUM_CHANNELS_PER_FRAME) { - /* how many frames did we expect ? */ - ++spektrum_state->FrameCnt; - if (spektrum_state->FrameCnt == TmpExpFrames) { - /* set the rc_available_flag */ - spektrum_state->RcAvailable = 1; - spektrum_state->FrameCnt = 0; - } - if (!secondary_receiver) { /* main receiver */ - EncodingType = TmpEncType; /* only update on a good */ - ExpectedFrames = TmpExpFrames; /* main receiver frame */ - } - spektrum_state->Sync = 0; - spektrum_state->ChannelCnt = 0; - spektrum_state->SecondFrame = 0; - spektrum_state->SpektrumTimer = MIN_FRAME_SPACE; - } -} - -/***************************************************************************** - * - * RadioControlEventImp decodes channel data stored by uart irq handlers - * and calls callback funtion - * - *****************************************************************************/ - -void RadioControlEventImp(void (*frame_handler)(void)) -{ - uint8_t ChannelCnt; - uint8_t ChannelNum; - uint16_t ChannelData; - uint8_t MaxChannelNum = 0; - -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - /* If we have two receivers and at least one of them has new data */ - uint8_t BestReceiver; - if ((PrimarySpektrumState.RcAvailable) || - (SecondarySpektrumState.RcAvailable)) { - /* if both receivers have new data select the one */ - /* that has had the least number of frames lost */ - if ((PrimarySpektrumState.RcAvailable) && - (SecondarySpektrumState.RcAvailable)) { - BestReceiver = (PrimarySpektrumState.LostFrameCnt - <= SecondarySpektrumState.LostFrameCnt) ? 0 : 1; - } else { - /* if only one of the receivers have new data use it */ - BestReceiver = (PrimarySpektrumState.RcAvailable) ? 0 : 1; - } - /* clear the data ready flags */ - PrimarySpektrumState.RcAvailable = 0; - SecondarySpektrumState.RcAvailable = 0; - -#else - /* if we have one receiver and it has new data */ - if (PrimarySpektrumState.RcAvailable) { - PrimarySpektrumState.RcAvailable = 0; -#endif - ChannelCnt = 0; - /* for every piece of channel data we have received */ - for (int i = 0; (i < SPEKTRUM_CHANNELS_PER_FRAME * ExpectedFrames); i++) { -#ifndef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - ChannelData = PrimarySpektrumState.values[i]; -#else - ChannelData = (!BestReceiver) ? PrimarySpektrumState.values[i] : - SecondarySpektrumState.values[i]; -#endif - /* find out the channel number and its value by */ - /* using the EncodingType which is only received */ - /* from the main receiver */ - switch (EncodingType) { - case (0) : /* 10 bit */ - ChannelNum = (ChannelData >> 10) & 0x0f; - /* don't bother decoding unused channels */ - if (ChannelNum < SPEKTRUM_NB_CHANNEL) { - SpektrumBuf[ChannelNum] = ChannelData & 0x3ff; - SpektrumBuf[ChannelNum] -= 0x200; - SpektrumBuf[ChannelNum] *= MAX_PPRZ / 0x156; - ChannelCnt++; - } - break; - - case (1) : /* 11 bit */ - ChannelNum = (ChannelData >> 11) & 0x0f; - /* don't bother decoding unused channels */ - if (ChannelNum < SPEKTRUM_NB_CHANNEL) { - SpektrumBuf[ChannelNum] = ChannelData & 0x7ff; - SpektrumBuf[ChannelNum] -= 0x400; - SpektrumBuf[ChannelNum] *= MAX_PPRZ / 0x2AC; - ChannelCnt++; - } - break; - - default : ChannelNum = 0x0F; break; /* never going to get here */ - } - /* store the value of the highest valid channel */ - if ((ChannelNum != 0x0F) && (ChannelNum > MaxChannelNum)) { - MaxChannelNum = ChannelNum; - } - - } - - /* if we have a valid frame the pass it to the frame handler */ - if (ChannelCnt >= (MaxChannelNum + 1)) { - radio_control.frame_cpt++; - radio_control.time_since_last_frame = 0; - radio_control.status = RC_OK; - /* since it is possible for the user use less than the actually available channels, - * we only transfer only Min(RADIO_CONTROL_NB_CHANNEL, available_channels) - */ - for (int i = 0; i < Min(RADIO_CONTROL_NB_CHANNEL, (MaxChannelNum + 1)); i++) { - radio_control.values[i] = SpektrumBuf[i]; - //Only values between +-MAX_PPRZ are allowed - Bound(radio_control.values[i], -MAX_PPRZ, MAX_PPRZ); - if (i == RADIO_THROTTLE) { - radio_control.values[i] += MAX_PPRZ; - radio_control.values[i] /= 2; - } - radio_control.values[i] *= SpektrumSigns[i]; - } - (*frame_handler)(); - } - } -} - - -/***************************************************************************** - * - * Initialise TIMx to fire an interrupt every 100 microseconds to provide - * timebase for SpektrumParser - * - *****************************************************************************/ -void SpektrumTimerInit(void) -{ - - /* enable TIMx clock */ - rcc_periph_clock_enable(RCC_TIMx); - - timer_reset(TIMx); - /* TIMx configuration, always counts up */ - timer_set_mode(TIMx, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // used to be 0 0 - /* 100 microseconds ie 0.1 millisecond */ - timer_set_period(TIMx, TIM_TICS_FOR_100us - 1); - uint32_t TIMx_clk = timer_get_frequency(TIMx); - /* timer ticks with 1us */ - timer_set_prescaler(TIMx, ((TIMx_clk / ONE_MHZ) - 1)); - - /* Enable TIMx interrupts */ -#ifdef STM32F1 - nvic_set_priority(NVIC_TIMx_IRQ, NVIC_TIMx_IRQ_PRIO); - nvic_enable_irq(NVIC_TIMx_IRQ); -#elif defined STM32F4 - /* the define says DAC IRQ, but it is also the global TIMx IRQ*/ - nvic_set_priority(NVIC_TIMx_DAC_IRQ, NVIC_TIMx_DAC_IRQ_PRIO); - nvic_enable_irq(NVIC_TIMx_DAC_IRQ); -#endif - - /* Enable TIMx Update interrupt */ - timer_enable_irq(TIMx, TIM_DIER_UIE); - timer_clear_flag(TIMx, TIM_SR_UIF); - - /* TIMx enable counter */ - timer_enable_counter(TIMx); -} - -/***************************************************************************** - * - * TIMx interrupt request handler updates times used by SpektrumParser - * - *****************************************************************************/ -#ifdef STM32F1 -void TIMx_ISR(void) -{ -#elif defined STM32F4 -void TIMx_DAC_ISR(void) { -#endif - - timer_clear_flag(TIMx, TIM_SR_UIF); - - if (PrimarySpektrumState.SpektrumTimer) { - --PrimarySpektrumState.SpektrumTimer; - } -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - if (SecondarySpektrumState.SpektrumTimer) { - --SecondarySpektrumState.SpektrumTimer; - } -#endif -} - -/***************************************************************************** - * - * Initialise the uarts for the spektrum satellite receivers - * - *****************************************************************************/ -void SpektrumUartInit(void) { - /* init RCC */ - gpio_enable_clock(PrimaryUart(_BANK)); - rcc_periph_clock_enable(PrimaryUart(_RCC)); - - /* Enable USART interrupts */ - nvic_set_priority(PrimaryUart(_IRQ), NVIC_PRIMARY_UART_PRIO); - nvic_enable_irq(PrimaryUart(_IRQ)); - - /* Init GPIOS */ - /* Primary UART Rx pin as floating input */ - gpio_setup_pin_af(PrimaryUart(_BANK), PrimaryUart(_PIN), PrimaryUart(_AF), FALSE); - - /* Configure Primary UART */ - usart_set_baudrate(PrimaryUart(_DEV), B115200); - usart_set_databits(PrimaryUart(_DEV), 8); - usart_set_stopbits(PrimaryUart(_DEV), USART_STOPBITS_1); - usart_set_parity(PrimaryUart(_DEV), USART_PARITY_NONE); - usart_set_flow_control(PrimaryUart(_DEV), USART_FLOWCONTROL_NONE); - usart_set_mode(PrimaryUart(_DEV), USART_MODE_RX); - - /* Enable Primary UART Receive interrupts */ - USART_CR1(PrimaryUart(_DEV)) |= USART_CR1_RXNEIE; - - /* Enable the Primary UART */ - usart_enable(PrimaryUart(_DEV)); - -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - /* init RCC */ - gpio_enable_clock(SecondaryUart(_BANK)); - rcc_periph_clock_enable(SecondaryUart(_RCC)); - - /* Enable USART interrupts */ - nvic_set_priority(SecondaryUart(_IRQ), NVIC_PRIMARY_UART_PRIO + 1); - nvic_enable_irq(SecondaryUart(_IRQ)); - - /* Init GPIOS */; - /* Secondary UART Rx pin as floating input */ - gpio_setup_pin_af(SecondaryUart(_BANK), SecondaryUart(_PIN), SecondaryUart(_AF), FALSE); - - /* Configure secondary UART */ - usart_set_baudrate(SecondaryUart(_DEV), B115200); - usart_set_databits(SecondaryUart(_DEV), 8); - usart_set_stopbits(SecondaryUart(_DEV), USART_STOPBITS_1); - usart_set_parity(SecondaryUart(_DEV), USART_PARITY_NONE); - usart_set_flow_control(SecondaryUart(_DEV), USART_FLOWCONTROL_NONE); - usart_set_mode(SecondaryUart(_DEV), USART_MODE_RX); - - /* Enable Secondary UART Receive interrupts */ - USART_CR1(SecondaryUart(_DEV)) |= USART_CR1_RXNEIE; - - /* Enable the Primary UART */ - usart_enable(SecondaryUart(_DEV)); -#endif - -} - -/***************************************************************************** - * - * The primary receiver UART interrupt request handler which passes the - * received character to Spektrum Parser. - * - *****************************************************************************/ -void PrimaryUart(_ISR)(void) { - - if (((USART_CR1(PrimaryUart(_DEV)) & USART_CR1_TXEIE) != 0) && - ((USART_SR(PrimaryUart(_DEV)) & USART_SR_TXE) != 0)) { - USART_CR1(PrimaryUart(_DEV)) &= ~USART_CR1_TXEIE; - } - - if (((USART_CR1(PrimaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) && - ((USART_SR(PrimaryUart(_DEV)) & USART_SR_RXNE) != 0)) { - uint8_t b = usart_recv(PrimaryUart(_DEV)); - SpektrumParser(b, &PrimarySpektrumState, FALSE); - } - -} - -/***************************************************************************** - * - * The secondary receiver UART interrupt request handler which passes the - * received character to Spektrum Parser. - * - *****************************************************************************/ -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT -void SecondaryUart(_ISR)(void) { - - if (((USART_CR1(SecondaryUart(_DEV)) & USART_CR1_TXEIE) != 0) && - ((USART_SR(SecondaryUart(_DEV)) & USART_SR_TXE) != 0)) { - USART_CR1(SecondaryUart(_DEV)) &= ~USART_CR1_TXEIE; - } - - if (((USART_CR1(SecondaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) && - ((USART_SR(SecondaryUart(_DEV)) & USART_SR_RXNE) != 0)) { - uint8_t b = usart_recv(SecondaryUart(_DEV)); - SpektrumParser(b, &SecondarySpektrumState, TRUE); - } - -} -#endif - - -/***************************************************************************** - * - * The following functions provide functionality to allow binding of - * spektrum satellite receivers. The pulse train sent to them means - * that AP is emulating a 9 channel JR-R921 24. - * By default, the same pin is used for pulse train and uart rx, but - * they can be different if needed - * - *****************************************************************************/ -#ifndef SPEKTRUM_PRIMARY_BIND_CONF_PORT -#define SPEKTRUM_PRIMARY_BIND_CONF_PORT PrimaryUart(_BANK) -#endif -#ifndef SPEKTRUM_PRIMARY_BIND_CONF_PIN -#define SPEKTRUM_PRIMARY_BIND_CONF_PIN PrimaryUart(_PIN) -#endif -#ifndef SPEKTRUM_SECONDARY_BIND_CONF_PORT -#define SPEKTRUM_SECONDARY_BIND_CONF_PORT SecondaryUart(_BANK) -#endif -#ifndef SPEKTRUM_SECONDARY_BIND_CONF_PIN -#define SPEKTRUM_SECONDARY_BIND_CONF_PIN SecondaryUart(_PIN) -#endif - -/***************************************************************************** - * - * radio_control_spektrum_try_bind(void) must called on powerup as spektrum - * satellites can only bind immediately after power up also it must be called - * before the call to SpektrumUartInit as we leave them with their Rx pins set - * as outputs. - * - *****************************************************************************/ -void radio_control_spektrum_try_bind(void) { -#ifdef SPEKTRUM_BIND_PIN_PORT -#ifdef SPEKTRUM_BIND_PIN_HIGH - /* Init GPIO for the bind pin, we enable the pulldown resistor. - * (esden) As far as I can tell only navstick is using the PIN LOW version of - * the bind pin, but I assume this should not harm anything. If I am mistaken - * than I appologise for the inconvenience. :) - */ - gpio_setup_input_pulldown(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN); - - sys_time_usleep(10); // wait for electrical level to stabilize - - /* exit if the BIND_PIN is low, it needs to - be pulled high at startup to initiate bind */ - if (gpio_get(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN) == 0) { - return; - } -#else - /* Init GPIO for the bind pin, we enable the pullup resistor in case we have - * a floating pin that does not have a hardware pullup resistor as it is the - * case with Lisa/M and Lisa/MX prior to version 2.1. - */ - gpio_setup_input_pullup(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN); - - sys_time_usleep(10); // wait for electrical level to stabilize - - /* exit if the BIND_PIN is high, it needs to - be pulled low at startup to initiate bind */ - if (gpio_get(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN) != 0) { - return; - } -#endif -#endif - - /* Master receiver Rx push-pull */ - gpio_setup_output(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); - - /* Master receiver RX line, drive high */ - gpio_set(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); - -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - /* Slave receiver Rx push-pull */ - gpio_setup_output(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); - - /* Slave receiver RX line, drive high */ - gpio_set(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); -#endif - - /* We have no idea how long the window for allowing binding after - power up is. This works for the moment but will need revisiting */ - sys_time_usleep(61000); - - for (int i = 0; i < MASTER_RECEIVER_PULSES ; i++) { - gpio_clear(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); - sys_time_usleep(118); - gpio_set(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); - sys_time_usleep(122); - } - -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - for (int i = 0; i < SLAVE_RECEIVER_PULSES; i++) { - gpio_clear(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); - sys_time_usleep(120); - gpio_set(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); - sys_time_usleep(120); - } -#endif /* RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT */ - - /* Set conf pin as input in case it is different from RX pin */ - gpio_setup_input(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); -#ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT - gpio_setup_input(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); -#endif -} diff --git a/sw/airborne/boards/apogee/chibios/v1.0/board.h b/sw/airborne/boards/apogee/chibios/v1.0/board.h index 5814edd991b..dd0704e5b9d 100644 --- a/sw/airborne/boards/apogee/chibios/v1.0/board.h +++ b/sw/airborne/boards/apogee/chibios/v1.0/board.h @@ -917,6 +917,28 @@ #define PPM_CHANNEL ICU_CHANNEL_1 #define PPM_TIMER ICUD1 +/* + * Spektrum + */ + +// shorter wait with chibios as the RTC oscillator takes longer to stabilize +#define SPEKTRUM_BIND_WAIT 30000 + +/* The line that is pulled low at power up to initiate the bind process + * PB15: AUX4 + */ +#define SPEKTRUM_BIND_PIN GPIO15 +#define SPEKTRUM_BIND_PIN_PORT GPIOB + +/* The line used to send the pulse train for the bind process + * When using UART2 on Apogee, this as to be a different pin than the uart2 rx + * Default pin for this is PA8: PPM_IN + */ +#ifndef SPEKTRUM_PRIMARY_BIND_CONF_PORT +#define SPEKTRUM_PRIMARY_BIND_CONF_PORT GPIOA +#define SPEKTRUM_PRIMARY_BIND_CONF_PIN GPIO8 +#endif + /* * PWM input */ diff --git a/sw/airborne/boards/apogee_1.0.h b/sw/airborne/boards/apogee_1.0.h index c7cb9430396..6accca0f56f 100644 --- a/sw/airborne/boards/apogee_1.0.h +++ b/sw/airborne/boards/apogee_1.0.h @@ -426,24 +426,6 @@ #define SPEKTRUM_PRIMARY_BIND_CONF_PIN GPIO8 #endif -/* Configuration of UART2 for Spektrum */ -#define SPEKTRUM_UART2_RCC RCC_USART2 -#define SPEKTRUM_UART2_BANK GPIOA -#define SPEKTRUM_UART2_PIN GPIO3 -#define SPEKTRUM_UART2_AF GPIO_AF7 -#define SPEKTRUM_UART2_IRQ NVIC_USART2_IRQ -#define SPEKTRUM_UART2_ISR usart2_isr -#define SPEKTRUM_UART2_DEV USART2 - -/* Configuration of UART6 for Spektrum */ -#define SPEKTRUM_UART6_RCC RCC_USART6 -#define SPEKTRUM_UART6_BANK GPIOC -#define SPEKTRUM_UART6_PIN GPIO7 -#define SPEKTRUM_UART6_AF GPIO_AF8 -#define SPEKTRUM_UART6_IRQ NVIC_USART6_IRQ -#define SPEKTRUM_UART6_ISR usart6_isr -#define SPEKTRUM_UART6_DEV USART6 - /* * IRQ Priorities */ diff --git a/sw/airborne/boards/chimera/chibios/v1.0/chimera.h b/sw/airborne/boards/chimera/chibios/v1.0/chimera.h index 1955657a0bf..d9126fec7c3 100644 --- a/sw/airborne/boards/chimera/chibios/v1.0/chimera.h +++ b/sw/airborne/boards/chimera/chibios/v1.0/chimera.h @@ -384,14 +384,37 @@ /** * UART3 (XBee slot), UART8 (GPS) and UART1 (Companion) - * are configured as UART from ChibiOS board file + * are configured as UART from ChibiOS board file by default */ +#define UART1_GPIO_PORT_TX GPIOB +#define UART1_GPIO_TX GPIO6 +#define UART1_GPIO_PORT_RX GPIOB +#define UART1_GPIO_RX GPIO7 +#define UART1_GPIO_AF 7 + +#define UART3_GPIO_PORT_TX GPIOD +#define UART3_GPIO_TX GPIO8 +#define UART3_GPIO_PORT_RX GPIOD +#define UART3_GPIO_RX GPIO9 +#define UART3_GPIO_AF 7 + +#define UART8_GPIO_PORT_TX GPIOE +#define UART8_GPIO_TX GPIO0 +#define UART8_GPIO_PORT_RX GPIOE +#define UART8_GPIO_RX GPIO1 +#define UART8_GPIO_AF 8 + /** - * SBUS + * SBUS / Spektrum port + * + * Recommended config: * * primary SBUS port is UART7, a.k.a. RC2 on Chimera board * secondary port (in dual driver) is UART4, a.k.a. RC1 on Chimera board + * + * primary Spektrum port is UART4, a.k.a. RC1 on Chimera board + * secondary port is UART7, a.k.a. RC2 on Chimera board */ // In case, do dynamic config of UARTs @@ -405,31 +428,18 @@ #define USE_UART4_RX TRUE #define USE_UART4_TX FALSE -#define UART4_GPIO_PORT_RX GPIOE -#define UART4_GPIO_RX GPIO7 +#define UART4_GPIO_PORT_RX GPIOA +#define UART4_GPIO_RX GPIO1 #define UART4_GPIO_AF 8 -/* - * Spektrum - * - * Not supported yet in chibios arch - * Only here for future reference - * - * primary Spektrum port is UART4, a.k.a. RC1 on Chimera board - * secondary port is UART7, a.k.a. RC2 on Chimera board +/* The line that is pulled low at power up to initiate the bind process + * PC7: AUX7 */ -/* The line that is pulled low at power up to initiate the bind process */ -/* These are not common between versions of lisa/mx and thus defined in the - * version specific header files. */ -#define SPEKTRUM_UART4_BANK UART4_GPIO_PORT_RX -#define SPEKTRUM_UART4_PIN UART4_GPIO_RX -#define SPEKTRUM_UART4_AF UART4_GPIO_AF -#define SPEKTRUM_UART4_DEV SD4 - -#define SPEKTRUM_UART7_BANK UART7_GPIO_PORT_RX -#define SPEKTRUM_UART7_PIN UART7_GPIO_RX -#define SPEKTRUM_UART7_AF UART7_GPIO_AF -#define SPEKTRUM_UART7_DEV SD7 +#define SPEKTRUM_BIND_PIN GPIO7 +#define SPEKTRUM_BIND_PIN_PORT GPIOC + +// no wait with chibios as the RTC oscillator takes longer to stabilize +#define SPEKTRUM_BIND_WAIT 30000 /** * PPM radio defines diff --git a/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h b/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h index ff559672163..26f0c1275a2 100644 --- a/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h +++ b/sw/airborne/boards/chimera/chibios/v1.0/mcuconf.h @@ -43,7 +43,11 @@ #define STM32_HSI_ENABLED TRUE #define STM32_LSI_ENABLED FALSE #define STM32_HSE_ENABLED TRUE +#if HAL_USE_RTC // disable LSE init if not needed to start faster #define STM32_LSE_ENABLED TRUE +#else +#define STM32_LSE_ENABLED FALSE +#endif #define STM32_CLOCK48_REQUIRED TRUE #define STM32_SW STM32_SW_PLL #define STM32_PLLSRC STM32_PLLSRC_HSE @@ -54,7 +58,11 @@ #define STM32_HPRE STM32_HPRE_DIV1 #define STM32_PPRE1 STM32_PPRE1_DIV4 #define STM32_PPRE2 STM32_PPRE2_DIV2 +#if HAL_USE_RTC #define STM32_RTCSEL STM32_RTCSEL_LSE +#else +#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK +#endif #define STM32_RTCPRE_VALUE 25 #define STM32_MCO1SEL STM32_MCO1SEL_HSE #define STM32_MCO1PRE STM32_MCO1PRE_DIV1 diff --git a/sw/airborne/boards/elle0_common.h b/sw/airborne/boards/elle0_common.h index bce675fe0c9..4fe13f50b24 100644 --- a/sw/airborne/boards/elle0_common.h +++ b/sw/airborne/boards/elle0_common.h @@ -121,30 +121,6 @@ #define SPEKTRUM_BIND_PIN GPIO0 #define SPEKTRUM_BIND_PIN_PORT GPIOB -#define SPEKTRUM_UART1_RCC RCC_USART1 -#define SPEKTRUM_UART1_BANK GPIOA -#define SPEKTRUM_UART1_PIN GPIO10 -#define SPEKTRUM_UART1_AF GPIO_AF7 -#define SPEKTRUM_UART1_IRQ NVIC_USART1_IRQ -#define SPEKTRUM_UART1_ISR usart1_isr -#define SPEKTRUM_UART1_DEV USART1 - -#define SPEKTRUM_UART2_RCC RCC_USART2 -#define SPEKTRUM_UART2_BANK GPIOA -#define SPEKTRUM_UART2_PIN GPIO3 -#define SPEKTRUM_UART2_AF GPIO_AF7 -#define SPEKTRUM_UART2_IRQ NVIC_USART2_IRQ -#define SPEKTRUM_UART2_ISR usart2_isr -#define SPEKTRUM_UART2_DEV USART2 - -#define SPEKTRUM_UART5_RCC RCC_UART5 -#define SPEKTRUM_UART5_BANK GPIOD -#define SPEKTRUM_UART5_PIN GPIO2 -#define SPEKTRUM_UART5_AF GPIO_AF8 -#define SPEKTRUM_UART5_IRQ NVIC_UART5_IRQ -#define SPEKTRUM_UART5_ISR uart5_isr -#define SPEKTRUM_UART5_DEV UART5 - /* PPM * * Default is PPM config 2, input on GPIOA1 (Servo pin 6) diff --git a/sw/airborne/mcu.c b/sw/airborne/mcu.c index 664f0077241..603586cb1ae 100644 --- a/sw/airborne/mcu.c +++ b/sw/airborne/mcu.c @@ -34,7 +34,7 @@ #include "led.h" #endif #if defined RADIO_CONTROL -#if defined RADIO_CONTROL_LINK || defined RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT +#if defined RADIO_CONTROL_BIND_IMPL_FUNC & defined SPEKTRUM_BIND_PIN_PORT #include "subsystems/radio_control.h" #endif #endif @@ -124,7 +124,7 @@ void mcu_init(void) PERIPHERAL3V3_ENABLE_ON(PERIPHERAL3V3_ENABLE_PORT, PERIPHERAL3V3_ENABLE_PIN); #endif /* for now this means using spektrum */ -#if defined RADIO_CONTROL & defined RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT & defined RADIO_CONTROL_BIND_IMPL_FUNC & defined SPEKTRUM_BIND_PIN_PORT +#if defined RADIO_CONTROL & defined RADIO_CONTROL_BIND_IMPL_FUNC & defined SPEKTRUM_BIND_PIN_PORT RADIO_CONTROL_BIND_IMPL_FUNC(); #endif #if USE_UART0 diff --git a/sw/airborne/subsystems/radio_control/joby_9ch.h b/sw/airborne/subsystems/radio_control/joby_9ch.h deleted file mode 100644 index c9bdef26a9b..00000000000 --- a/sw/airborne/subsystems/radio_control/joby_9ch.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2008-2009 Antoine Drouin - * - * This file is part of paparazzi. - * - * paparazzi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * paparazzi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef RADIO_CONTROL_JOBY_9CH_H -#define RADIO_CONTROL_JOBY_9CH_H - -#define RADIO_CONTROL_NB_CHANNEL 9 - -#define RADIO_THROTTLE 0 -#define RADIO_YAW 1 -#define RADIO_PITCH 2 -#define RADIO_ROLL 3 -#define RADIO_GEAR 4 -#define RADIO_MODE 5 -#define RADIO_AUX2 6 -#define RADIO_AUX3 7 -#define RADIO_KILL 8 - -#define RC_JOBY_SYNC_2 0x12 - -#define RC_JOBY_SIGNS { 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1 } - -#endif /* RADIO_CONTROL_JOBY_9CH_H */ diff --git a/sw/airborne/subsystems/radio_control/spektrum.c b/sw/airborne/subsystems/radio_control/spektrum.c index f606c2f9361..4db6df00fd5 100644 --- a/sw/airborne/subsystems/radio_control/spektrum.c +++ b/sw/airborne/subsystems/radio_control/spektrum.c @@ -1,5 +1,8 @@ /* * Copyright (C) 2008-2009 Antoine Drouin + * 2010 Eric Parsonage + * 2015 Freek van Tienen + * 2018 Gautier Hattenberger * * This file is part of paparazzi. * @@ -14,16 +17,363 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * along with paparazzi; see the file COPYING. If not, see + * . */ -#include "spektrum.h" +#include "subsystems/radio_control/spektrum.h" -/* Currently the functionality has been pushed into the arch directories - * both arch directories contain essentially the original parser. - * The next step is to implement a new parser for lisa. Once this is complete - * hardware dependent functions will be written for booz then the lisa parser - * will end up in here +/** + * @file subsystems/radio_control/spektrum.c + * + * Spektrum sattelite receiver implementation. For the protocol specification see: + * http://www.spektrumrc.com/ProdInfo/Files/Remote%20Receiver%20Interfacing%20Rev%20A.pdf + */ + +#include "std.h" +#include "subsystems/radio_control.h" +#include "mcu_periph/uart.h" +#include "mcu_periph/gpio.h" +#include "mcu_periph/sys_time.h" + +/* Check if primary receiver is defined */ +#ifndef SPEKTRUM_PRIMARY_UART +#error "You must at least define the primary Spektrum satellite receiver." +#endif + +/* Changed radio control order Notice */ +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") + +/* Number of low pulses sent during binding to the satellite receivers + * As recommended, master and slave receivers are in DSMX 11ms mode, + * other modes (DSM2, 22ms) will be automatically supported + */ +#define SPEKTRUM_MASTER_RECEIVER_PULSES 9 // only one receiver should be in master mode +#define SPEKTRUM_SLAVE_RECEIVER_PULSES 10 + +/* Set polarity using RC_POLARITY_GPIO. */ +#ifndef RC_SET_POLARITY +#define RC_SET_POLARITY gpio_clear +#endif + +/* Busy wait to let the receiver starts properly + * This should be reduced when the MCU takes longer to start + */ +#ifndef SPEKTRUM_BIND_WAIT +#define SPEKTRUM_BIND_WAIT 60000 +#endif + +// in case the number of channel is less than maximum +const int8_t spektrum_signs[] = RADIO_CONTROL_SPEKTRUM_SIGNS; + +/* Default spektrum values */ +static struct spektrum_t spektrum = { + .valid = false, + .tx_type = 0, // unknown type +}; + +/** Allowed system field valaues. + * from datasheet, possible values for the frame format + * encoded in the system field of the internal remote + * frame (second byte). + * Only the first one is encoding values on 10bits, + * other ones on 11bits. + */ +#define SPEKTRUM_SYS_22_1024_2 0x01 // 22ms 1024 DSM2 +#define SPEKTRUM_SYS_11_2048_2 0x12 // 11ms 2048 DSM2 +#define SPEKTRUM_SYS_22_2048_X 0xa2 // 22ms 2048 DSMX +#define SPEKTRUM_SYS_11_2048_X 0xb2 // 11ms 2048 DSMX + +static void spektrum_bind(void); + +/** Initialize a spektrum sattelite */ +static inline void spektrum_init_sat(struct spektrum_sat_t *sat) +{ + sat->valid = false; + sat->timer = get_sys_time_msec(); + sat->idx = 0; + + // Initialize values + for (uint8_t i = 0; i < SPEKTRUM_MAX_CHANNELS; i++) { + sat->values[i] = 0; + } +} + +/***************************************************************************** + * + * spektrum_try_bind(void) must called on powerup as spektrum + * satellites can only bind immediately after power up also it must be called + * before the call to SpektrumUartInit as we leave them with their Rx pins set + * as outputs. + * + *****************************************************************************/ +void spektrum_try_bind(void) +{ +#ifdef SPEKTRUM_BIND_PIN_PORT +#ifdef SPEKTRUM_BIND_PIN_HIGH + /* Init GPIO for the bind pin, we enable the pulldown resistor. + * (esden) As far as I can tell only navstick is using the PIN LOW version of + * the bind pin, but I assume this should not harm anything. If I am mistaken + * than I appologise for the inconvenience. :) + */ + gpio_setup_input_pulldown(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN); + + sys_time_usleep(10); // wait for electrical level to stabilize + + /* Exit if the BIND_PIN is low, it needs to + be pulled high at startup to initiate bind */ + if (gpio_get(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN) != 0) { + spektrum_bind(); + } +#else + /* Init GPIO for the bind pin, we enable the pullup resistor in case we have + * a floating pin that does not have a hardware pullup resistor as it is the + * case with Lisa/M and Lisa/MX prior to version 2.1. + */ + gpio_setup_input_pullup(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN); + + sys_time_usleep(10); // wait for electrical level to stabilize + + /* Exit if the BIND_PIN is high, it needs to + be pulled low at startup to initiate bind */ + if (gpio_get(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN) == 0) { + spektrum_bind(); + } +#endif +#endif +} + + +/** Main Radio initialization */ +void radio_control_impl_init(void) +{ + + for (uint8_t i = 0; i < RADIO_CONTROL_NB_CHANNEL; i++) { + spektrum.signs[i] = spektrum_signs[i]; + } + + // Set polarity to normal on boards that can change this +#ifdef RC_POLARITY_GPIO_PORT + gpio_setup_output(RC_POLARITY_GPIO_PORT, RC_POLARITY_GPIO_PIN); + RC_SET_POLARITY(RC_POLARITY_GPIO_PORT, RC_POLARITY_GPIO_PIN); +#endif + + // Initialize all the UART's in the satellites + spektrum_init_sat(&spektrum.satellites[0]); +#ifdef SPEKTRUM_SECONDARY_UART + spektrum_init_sat(&spektrum.satellites[1]); +#endif +} + +/* Parse a sattelite channel */ +static inline void spektrum_parse_channel(struct spektrum_sat_t *sat, uint16_t chan) +{ + // This channel is not used + if (chan == 0xFFFF) { + return; + } + + if (spektrum.tx_type == SPEKTRUM_SYS_22_1024_2) { + // We got a 10bit precision packet + uint8_t chan_num = (chan & 0xFC00) >> 10; + sat->values[chan_num] = chan & 0x03FF; + if (chan_num == RADIO_THROTTLE) { + // scale full range to pprz_t + // but since 1024 correspond to 150%, scale with 1024/1.5 ~ 684 + // remove an offset of 2400 = 171 * MAX_PPRZ / 684 + sat->values[chan_num] = ((MAX_PPRZ * sat->values[chan_num]) / 684) - 2400; + } else { + sat->values[chan_num] -= (1 << 9); // substract 2^9 to get a value between [-512;512] + // scale full range to pprz_t + // but since 512 correspond to 150%, scale with 512/1.5 ~ 342 + sat->values[chan_num] = (MAX_PPRZ * sat->values[chan_num]) / 342; + } + } + else { + // We got a 11bit precision packet + uint8_t chan_num = (chan & 0x7800) >> 11; + sat->values[chan_num] = chan & 0x07FF; + if (chan_num == RADIO_THROTTLE) { + // scale full range to pprz_t + // but since 2048 correspond to 150%, scale with 2048/1.5 ~ 1368 + // remove an offset of 2400 = 234 * MAX_PPRZ / 1368 + sat->values[chan_num] = ((MAX_PPRZ * sat->values[chan_num]) / 1368) - 2400; + } else { + sat->values[chan_num] -= (1 << 10); // substract 2^10 to get a value between [-1024;1024] + // scale full range to pprz_t + // but since 1024 correspond to 150%, scale with 1024/1.5 ~ 684 + sat->values[chan_num] = (MAX_PPRZ * sat->values[chan_num]) / 684; + } + } + + // mark a valid frame + sat->valid = true; + spektrum.valid = true; +} + +/* Spektrum parser for a satellite */ +static inline void spektrum_parser(struct spektrum_sat_t *sat) +{ + // Parse packet + sat->lost_frame_cnt = sat->buf[0]; + // For now ignore the second byte (which could be the TX type) + // if frame type is still unknown, try to find it in the 'system' byte + // only the primary receiver should have a valid type + if (spektrum.tx_type == 0) { + uint8_t type = sat->buf[1]; + if (type == SPEKTRUM_SYS_22_1024_2 || type == SPEKTRUM_SYS_11_2048_2 || + type == SPEKTRUM_SYS_22_2048_X || type == SPEKTRUM_SYS_11_2048_X) { + // we have a valid type, we assume it comes from primary receiver + spektrum.tx_type = type; + } else { + // return and drop frame as we don't know what to do with it + return; + } + } + // parse servo channels + for (uint8_t i = 2; i < 2*SPEKTRUM_CHANNELS_PER_FRAME+2; i = i+2) { + uint16_t chan = (((uint16_t)sat->buf[i]) << 8) | ((uint16_t)sat->buf[i+1]); + spektrum_parse_channel(sat, chan); + } +} + +/** Check bytes on the UART */ +static void spektrum_uart_check(struct uart_periph *dev, struct spektrum_sat_t *sat) +{ + // detect sync space based on frame spacing + uint32_t t = get_sys_time_msec(); + if (t - sat->timer > SPEKTRUM_MIN_FRAME_SPACE) { + sat->timer = t; // reset counter + uint16_t bytes_cnt = uart_char_available(dev); // The amount of bytes in the buffer + // sync space detected but buffer not empty, flush data + if (bytes_cnt > 0) { + for (uint8_t i = 0; i < bytes_cnt; i++) { + uart_getch(dev); + } + } + } + // check and parse bytes in uart buffer + while (uart_char_available(dev)) { + sat->buf[sat->idx++] = uart_getch(dev); + sat->timer = t; // reset counter + if (sat->idx == SPEKTRUM_FRAME_LEN) { + // buffer is full, parse frame + spektrum_parser(sat); + sat->idx = 0; // reset index + break; // stop here to handle RC frame + } + } +} + +/** Checks if there is one valid satellite and sets the radio_control structure */ +void spektrum_event(void (*frame_handler)(void)) +{ + spektrum_uart_check(&SPEKTRUM_PRIMARY_UART, &spektrum.satellites[0]); + +#ifdef SPEKTRUM_SECONDARY_UART + spektrum_uart_check(&SPEKTRUM_SECONDARY_UART, &spektrum.satellites[1]); +#endif + + // Whenever we received a valid RC packet + if (spektrum.valid) { + uint8_t sat_id = SPEKTRUM_SATELLITES_NB; + spektrum.valid = false; + + // Find the first satellite that has a valid packet + for (uint8_t i = 0; i < SPEKTRUM_SATELLITES_NB; i++) { + if (i < sat_id) { + sat_id = i; + } + if (spektrum.satellites[i].valid) { + spektrum.satellites[i].valid = false; + } + } + + // Failsafe case if found satellite is out of bound (Should not happen) + if (sat_id >= SPEKTRUM_SATELLITES_NB) { + return; + } + + // Set the radio control status + radio_control.frame_cpt++; + radio_control.time_since_last_frame = 0; + radio_control.status = RC_OK; + + // Copy the radio control channels + for (uint8_t i = 0; i < RADIO_CONTROL_NB_CHANNEL; i++) { + radio_control.values[i] = spektrum.satellites[sat_id].values[i] * spektrum.signs[i]; + Bound(radio_control.values[i], -MAX_PPRZ, MAX_PPRZ); + } + + // We got a valid frame so execute the frame handler + (*frame_handler)(); + } +} + +/* Defines needed for easy access of port information */ +#define _UART_RX_PORT(i) i ## _PORT_RX +#define UART_RX_PORT(i) _UART_RX_PORT(i) +#define _UART_RX(i) i ## _RX +#define UART_RX(i) _UART_RX(i) + +/** + * By default, the same pin is used for pulse train and uart rx, but + * they can be different if needed + */ +#ifndef SPEKTRUM_PRIMARY_BIND_CONF_PORT +#define SPEKTRUM_PRIMARY_BIND_CONF_PORT UART_RX_PORT(SPEKTRUM_PRIMARY_UART_UPPER) +#endif +#ifndef SPEKTRUM_PRIMARY_BIND_CONF_PIN +#define SPEKTRUM_PRIMARY_BIND_CONF_PIN UART_RX(SPEKTRUM_PRIMARY_UART_UPPER) +#endif +#ifndef SPEKTRUM_SECONDARY_BIND_CONF_PORT +#define SPEKTRUM_SECONDARY_BIND_CONF_PORT UART_RX_PORT(SPEKTRUM_SECONDARY_UART_UPPER) +#endif +#ifndef SPEKTRUM_SECONDARY_BIND_CONF_PIN +#define SPEKTRUM_SECONDARY_BIND_CONF_PIN UART_RX(SPEKTRUM_SECONDARY_UART_UPPER) +#endif + +/** This function puts the satellite in binding mode. + * The requirement of this are that this needs to be done while powering up. */ +static void spektrum_bind(void) +{ + + /* Master receiver Rx push-pull */ + gpio_setup_output(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); + /* Master receiver RX line, drive high */ + gpio_set(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); + +#ifdef SPEKTRUM_SECONDARY_UART + /* Slave receiver Rx push-pull */ + gpio_setup_output(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); + /* Slave receiver RX line, drive high */ + gpio_set(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); +#endif + + /* bind pulses should be issued within 200ms after power up + * wait a bit to let the receiver start properly, + * set to 0 to disable */ +#if SPEKTRUM_BIND_WAIT + sys_time_usleep(SPEKTRUM_BIND_WAIT); +#endif + + /* Transmit the bind pulses */ + for (int i = 0; i < 2 * SPEKTRUM_MASTER_RECEIVER_PULSES ; i++) { + gpio_toggle(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); + sys_time_usleep(120); + } +#ifdef SPEKTRUM_SECONDARY_UART + for (int i = 0; i < 2 * SPEKTRUM_SLAVE_RECEIVER_PULSES; i++) { + gpio_toggle(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); + sys_time_usleep(120); + } +#endif + + /* Set conf pin as input in case it is different from RX pin */ + gpio_setup_input(SPEKTRUM_PRIMARY_BIND_CONF_PORT, SPEKTRUM_PRIMARY_BIND_CONF_PIN); +#ifdef SPEKTRUM_SECONDARY_UART + gpio_setup_input(SPEKTRUM_SECONDARY_BIND_CONF_PORT, SPEKTRUM_SECONDARY_BIND_CONF_PIN); +#endif +} + diff --git a/sw/airborne/subsystems/radio_control/spektrum.h b/sw/airborne/subsystems/radio_control/spektrum.h index a544cbf8afd..70a592690ac 100644 --- a/sw/airborne/subsystems/radio_control/spektrum.h +++ b/sw/airborne/subsystems/radio_control/spektrum.h @@ -1,5 +1,7 @@ /* * Copyright (C) 2009-2014 The Paparazzi Team + * 2015 Freek van Tienen + * 2018 Gautier Hattenberger * * This file is part of paparazzi. * @@ -27,12 +29,44 @@ #ifndef RADIO_CONTROL_SPEKTRUM_H #define RADIO_CONTROL_SPEKTRUM_H -/* implemented in arch/xxx/subsystems/radio_control/spektrum_arch.c */ -extern void radio_control_spektrum_try_bind(void); +#include "std.h" -#include "subsystems/radio_control/spektrum_arch.h" -/* implemented in arch/xxx/subsystems/radio_control/spektrum_arch.c */ +/* Include channels information */ +#include "spektrum_radio.h" -#define RadioControlEvent(_received_frame_handler) RadioControlEventImp(_received_frame_handler) +/* For now only two satellites are supported */ +#define SPEKTRUM_SATELLITES_NB 2 + +/* Timings and maximums of Spektrum DSM protocol */ +#define SPEKTRUM_FRAME_LEN 16 ///< 16 bytes in a standard frame +#define SPEKTRUM_CHANNELS_PER_FRAME 7 ///< Maximum amount of RC channels per frame +#define SPEKTRUM_MAX_FRAMES 2 ///< Maximum amount of RC frames containing different channels +#define SPEKTRUM_MAX_CHANNELS (SPEKTRUM_CHANNELS_PER_FRAME * SPEKTRUM_MAX_FRAMES) +#define SPEKTRUM_MIN_FRAME_SPACE 7 ///< Minum amount of time between frames (7ms), in fact either 11 or 22 ms + +/* Set the event function to the correct */ +#define RadioControlEvent(_received_frame_handler) spektrum_event(_received_frame_handler) + +/* Per satellite we keep track of data */ +struct spektrum_sat_t { + bool valid; ///< True when we received a packet else false + uint32_t timer; ///< Timer to keep track of the UART synchronisation + uint8_t lost_frame_cnt; ///< Amount of RC frames lost + uint8_t buf[SPEKTRUM_FRAME_LEN]; ///< input buffer + uint8_t idx; ///< input buffer index + int16_t values[SPEKTRUM_MAX_CHANNELS]; ///< RC channel values +}; + +/* Main spektrum structure */ +struct spektrum_t { + bool valid; ///< True when we received a packet else false + uint8_t tx_type; ///< Transmitter type encoded (see wiki) + int8_t signs[RADIO_CONTROL_NB_CHANNEL]; ///< Signs for the RC channels + struct spektrum_sat_t satellites[SPEKTRUM_SATELLITES_NB]; ///< All the satellites connected +}; + +/* External functions */ +extern void spektrum_event(void (*_received_frame_handler)(void)); +extern void spektrum_try_bind(void); #endif /* RADIO_CONTROL_SPEKTRUM_H */ diff --git a/sw/airborne/subsystems/radio_control/spektrum_dx7se.h b/sw/airborne/subsystems/radio_control/spektrum_dx7se.h deleted file mode 100644 index 42463e5c3d2..00000000000 --- a/sw/airborne/subsystems/radio_control/spektrum_dx7se.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008-2009 Antoine Drouin - * - * This file is part of paparazzi. - * - * paparazzi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * paparazzi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef RADIO_CONTROL_SPEKTRUM_DX7SE_H -#define RADIO_CONTROL_SPEKTRUM_DX7SE_H - -#define RADIO_CONTROL_NB_CHANNEL 7 - -#define RADIO_ROLL 0 -#define RADIO_THROTTLE 1 -#define RADIO_PITCH 2 -#define RADIO_YAW 3 -#define RADIO_AUX3 4 -#define RADIO_MODE 5 -#define RADIO_AUX4 6 - -#define RC_SPK_SYNC_2 0x12 - -#define RC_SPK_THROWS { MAX_PPRZ/MAX_SPK, \ - MAX_PPRZ/MAX_SPK, \ - -MAX_PPRZ/MAX_SPK, \ - MAX_PPRZ/MAX_SPK, \ - MAX_PPRZ/MAX_SPK, \ - -MAX_PPRZ/MAX_SPK, \ - MAX_PPRZ/MAX_SPK } - -/* - aileron 1 - elevator 2 - rudder 3 - gear 4 - throttle 5 -*/ - -#endif /* RADIO_CONTROL_SPEKTRUM_DX7SE_H */ diff --git a/sw/airborne/subsystems/radio_control/spektrum_dx7se_joby.h b/sw/airborne/subsystems/radio_control/spektrum_dx7se_joby.h deleted file mode 100644 index 7a468a471b6..00000000000 --- a/sw/airborne/subsystems/radio_control/spektrum_dx7se_joby.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008-2009 Antoine Drouin - * - * This file is part of paparazzi. - * - * paparazzi is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * paparazzi is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef RADIO_CONTROL_SPEKTRUM_DX7SE_H -#define RADIO_CONTROL_SPEKTRUM_DX7SE_H - -#define RADIO_CONTROL_NB_CHANNEL 7 - -#define RADIO_ROLL 0 -#define RADIO_THROTTLE 5 -#define RADIO_PITCH 3 -#define RADIO_YAW 6 -#define RADIO_MODE 1 -#define RADIO_KILL_SWITCH 4 - -#define RC_SPK_SYNC_2 0x01 - -#define RC_SPK_THROWS { MAX_PPRZ/MAX_SPK, \ - MAX_PPRZ/MAX_SPK, \ - -MAX_PPRZ/MAX_SPK, \ - -MAX_PPRZ/MAX_SPK, \ - -MAX_PPRZ/MAX_SPK, \ - MAX_PPRZ/MAX_SPK, \ - MAX_PPRZ/MAX_SPK } - -/* - aileron 1 - elevator 2 - rudder 3 - gear 4 - throttle 5 -*/ - -#endif /* RADIO_CONTROL_SPEKTRUM_DX7SE_H */ diff --git a/sw/airborne/arch/stm32/subsystems/radio_control/spektrum_arch.h b/sw/airborne/subsystems/radio_control/spektrum_radio.h similarity index 55% rename from sw/airborne/arch/stm32/subsystems/radio_control/spektrum_arch.h rename to sw/airborne/subsystems/radio_control/spektrum_radio.h index 753deeaabec..0a3af0b4895 100644 --- a/sw/airborne/arch/stm32/subsystems/radio_control/spektrum_arch.h +++ b/sw/airborne/subsystems/radio_control/spektrum_radio.h @@ -1,5 +1,6 @@ /* - * Copyright (C) 2010 Eric Parsonage + * Copyright (C) 2009-2014 The Paparazzi Team + * 2016 Freek van Tienen * * This file is part of paparazzi. * @@ -14,29 +15,26 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with paparazzi; see the file COPYING. If not, write to - * the Free Software Foundation, 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * + * along with paparazzi; see the file COPYING. If not, see + * . */ -#ifndef RADIO_CONTROL_SPEKTRUM_ARCH_H -#define RADIO_CONTROL_SPEKTRUM_ARCH_H - - -/* - * All Spektrum and JR 2.4 GHz transmitters - * have the same channel assignments. +/** + * @file subsystems/radio_control/spektrum_radio.h + * + * Radio control channels defaults, because they are digital */ -#define SPEKTRUM_NB_CHANNEL 12 +#ifndef RADIO_CONTROL_SPEKTRUM_RADIO_H +#define RADIO_CONTROL_SPEKTRUM_RADIO_H +/* Amount of spektrum channels */ #ifndef RADIO_CONTROL_NB_CHANNEL -#define RADIO_CONTROL_NB_CHANNEL 12 +#define RADIO_CONTROL_NB_CHANNEL 14 #endif -#if RADIO_CONTROL_NB_CHANNEL > 12 -#error "RADIO_CONTROL_NB_CHANNEL mustn't be higher than 12." +#if RADIO_CONTROL_NB_CHANNEL > 14 +#error "RADIO_CONTROL_NB_CHANNEL mustn't be higher than 14." #endif /* default channel assignments */ @@ -52,12 +50,8 @@ #ifndef RADIO_YAW #define RADIO_YAW 3 #endif -#ifndef RADIO_GEAR #define RADIO_GEAR 4 -#endif -#ifndef RADIO_FLAP #define RADIO_FLAP 5 -#endif #define RADIO_AUX1 5 #define RADIO_AUX2 6 #define RADIO_AUX3 7 @@ -65,25 +59,22 @@ #define RADIO_AUX5 9 #define RADIO_AUX6 10 #define RADIO_AUX7 11 +#define RADIO_AUX8 12 +#define RADIO_AUX9 13 + +/* Default Mode channel is GEAR (number 5) */ +#ifndef RADIO_MODE +#define RADIO_MODE RADIO_GEAR +#endif -/* reverse some channels to suit Paparazzi conventions */ -/* the maximum number of channels a Spektrum can transmit is 12 */ +/* Possibility to reverse channels */ #ifndef RADIO_CONTROL_SPEKTRUM_SIGNS +// #ifdef RADIO_CONTROL_SPEKTRUM_OLD_SIGNS -#define RADIO_CONTROL_SPEKTRUM_SIGNS {1,-1,-1,-1,1,-1,1,1,1,1,1,1} // As most transmitters are sold +#define RADIO_CONTROL_SPEKTRUM_SIGNS {1,-1,-1,-1,1,-1,1,1,1,1,1,1,1,1} // As most transmitters are sold #else -#define RADIO_CONTROL_SPEKTRUM_SIGNS {1,1,1,1,1,1,1,1,1,1,1,1} // PPRZ sign convention -#endif +#define RADIO_CONTROL_SPEKTRUM_SIGNS {1,1,1,1,1,1,1,1,1,1,1,1,1,1} // PPRZ sign convention #endif - -/* really for a 9 channel transmitter - we would swap the order of these */ -#ifndef RADIO_MODE -#define RADIO_MODE RADIO_GEAR #endif -extern void RadioControlEventImp(void (*_received_frame_handler)(void)); -/* initialise the uarts used by the parser */ -void SpektrumUartInit(void); - -#endif /* RADIO_CONTROL_SPEKTRUM_ARCH_H */ +#endif /* RADIO_CONTROL_SPEKTRUM_RADIO_H */