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 */