paparazzi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[paparazzi-commits] [5680] new spektrum parser


From: Eric
Subject: [paparazzi-commits] [5680] new spektrum parser
Date: Wed, 25 Aug 2010 18:42:37 +0000

Revision: 5680
          http://svn.sv.gnu.org/viewvc/?view=rev&root=paparazzi&revision=5680
Author:   lamestllama
Date:     2010-08-25 18:42:37 +0000 (Wed, 25 Aug 2010)
Log Message:
-----------
new spektrum parser

Modified Paths:
--------------
    
paparazzi3/trunk/sw/airborne/booz/arch/stm32/radio_control/booz_radio_control_spektrum_arch.c

Modified: 
paparazzi3/trunk/sw/airborne/booz/arch/stm32/radio_control/booz_radio_control_spektrum_arch.c
===================================================================
--- 
paparazzi3/trunk/sw/airborne/booz/arch/stm32/radio_control/booz_radio_control_spektrum_arch.c
       2010-08-25 18:42:28 UTC (rev 5679)
+++ 
paparazzi3/trunk/sw/airborne/booz/arch/stm32/radio_control/booz_radio_control_spektrum_arch.c
       2010-08-25 18:42:37 UTC (rev 5680)
@@ -25,36 +25,30 @@
 #include <stm32/gpio.h>
 #include <stm32/rcc.h>
 #include <stm32/tim.h>
-#include BOARD_CONFIG
+#include <stm32/misc.h>
+#include <stm32/usart.h>
 #include "uart.h"
 #include "booz_radio_control.h"
 #include "booz_radio_control_spektrum_arch.h"
+#include "booz2_autopilot.h"
 
-bool_t   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;
 
-/* set TIM1 to run at DELAY_TIM_FREQUENCY */ 
-static void delay_init( void );
-/* wait busy loop, microseconds */
-static void delay_us( uint16_t uSecs );
-/* wait busy loop, milliseconds */
-static void delay_ms( uint16_t mSecs ); 
- 
-/* The longest delay with micro second granularity */
 #define MAX_DELAY   INT16_MAX
 /* the frequency of the delay timer */
 #define DELAY_TIM_FREQUENCY 1000000
 /* Number of low pulses sent to satellite receivers */ 
-#define MASTER_RECEIVER_PULSES 3 
-#define SLAVE_RECEIVER_PULSES 4 
+#define MASTER_RECEIVER_PULSES 5 
+#define SLAVE_RECEIVER_PULSES 6
 
 /* The line that is pulled low at power up to initiate the bind process */  
 #define BIND_PIN GPIO_Pin_3
 #define BIND_PIN_PORT GPIOC
 #define BIND_PIN_PERIPH RCC_APB2Periph_GPIOC 
 
+#define TIM_FREQ_1000000 1000000
+#define TIM_TICS_FOR_100us 100
+#define MIN_FRAME_SPACE  70  // 7ms
+#define MAX_BYTE_SPACE  3   // .3ms
 
 /*
  * in the makefile we set RADIO_CONTROL_LINK to be Uartx
@@ -62,94 +56,620 @@
  * defined as uartx these macros give us the glue 
  * that allows static calls at compile time 
  */
+ 
 
-#define Uart1_init uart1_init()
-#define Uart2_init uart2_init()
-#define Uart3_init uart3_init()
-#define Uart5_init uart5_init()
 
-#define __MasterRcLink(dev, _x) dev##_x
-#define _MasterRcLink(dev, _x)  __MasterRcLink(dev, _x)
-#define MasterRcLink(_x) _MasterRcLink(RADIO_CONTROL_LINK, _x)
+#define __PrimaryUart(dev, _x) dev##_x
+#define _PrimaryUart(dev, _x)  __PrimaryUart(dev, _x)
+#define PrimaryUart(_x) _PrimaryUart(RADIO_CONTROL_LINK, _x)
 
-#define __SlaveRcLink(dev, _x) dev##_x
-#define _SlaveRcLink(dev, _x)  __SlaveRcLink(dev, _x)
-#define SlaveRcLink(_x) _SlaveRcLink(RADIO_CONTROL_LINK_SLAVE, _x)
+#define __SecondaryUart(dev, _x) dev##_x
+#define _SecondaryUart(dev, _x)  __SecondaryUart(dev, _x)
+#define SecondaryUart(_x) _SecondaryUart(RADIO_CONTROL_LINK_SLAVE, _x)
 
-/*
- * bind() init must called on powerup as the spektrum 
- * satellites can only bind immediately after power up
- * also it must be called before we call uartx_init()
- * as we leave them with their Rx pins set as outputs
- */    
-void radio_control_spektrum_try_bind( void ) {
+SpektrumStateType PrimarySpektrumState = {1,0,0,0,0,0,0,0,0};
+#ifdef RADIO_CONTROL_LINK_SLAVE 
+SpektrumStateType SecondarySpektrumState = {1,0,0,0,0,0,0,0,0};
+#endif
 
+int16_t SpektrumBuf[SPEKTRUM_CHANNELS_PER_FRAME*MAX_SPEKTRUM_FRAMES];
+/* the order of the channels on a spektrum is always as follows :
+ *
+ * Throttle
+ * Aileron
+ * Elevator
+ * Rudder
+ * Gear
+ * Flap/Aux1
+ * Aux2
+ * Aux3
+ * Aux4
+ *
+ */
+int8_t SpektrumSigns[MAX_SPEKTRUM_CHANNELS] = {1,1,-1,1,1,-1,1,1,1,1,1,1};
+
+static uint8_t EncodingType = 0;
+static uint8_t ExpectedFrames = 0;
+
+void SpektrumUartInit(void);
+void SpektrumTimerInit(void);
+void DebugInit(void);
+ 
+
+void tim1_up_irq_handler(void);
+/* wait busy loop, microseconds */
+static void DelayUs( uint16_t uSecs );
+/* wait busy loop, milliseconds */
+static void DelayMs( uint16_t mSecs ); 
+/* setup timer 1 for busy wait delays */
+static void SpektrumDelayInit( void );
+
+
+void radio_control_impl_init(void) {
+  SpektrumTimerInit();
+  // DebugInit();  
+  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.
+ *
+ * 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
+ *
+ *****************************************************************************/
+
+#define SpektrumParser(_c, _SpektrumState, _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 = (!_SpektrumState.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 ((_SpektrumState.ReSync == 1) ||                                         \
+      ((_SpektrumState.Sync == 0) && (!TimedOut))) {                          \
+                                                                              \
+    _SpektrumState.ReSync = 0;                                                \
+    _SpektrumState.SpektrumTimer = MIN_FRAME_SPACE;                           \
+    _SpektrumState.Sync = 0;                                                  \
+    _SpektrumState.ChannelCnt = 0;                                            \
+    _SpektrumState.FrameCnt = 0;                                              \
+    _SpektrumState.SecondFrame = 0;                                           \
+    return;                                                                   \
+  }                                                                           \
+                                                                              \
+  /* 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 (_SpektrumState.Sync == 0) {                                             \
+      _SpektrumState.LostFrameCnt = _c;                                       \
+      if(_receiver) /* secondary receiver */                                  \
+        _SpektrumState.LostFrameCnt = _SpektrumState.LostFrameCnt << 8;       \
+      _SpektrumState.Sync = 1;                                                \
+      _SpektrumState.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) {                                                              \
+    _SpektrumState.ReSync = 1;                                                \
+    /* next frame not expected sooner than 7ms     */                         \
+    _SpektrumState.SpektrumTimer = MIN_FRAME_SPACE;                           \
+    return;                                                                   \
+  }                                                                           \
+                                                                              \
+  /* second character determines resolution and frame rate for main */        \
+  /* receiver or low byte of LostFrameCount for secondary receiver  */        \
+  if(_SpektrumState.Sync == 1) {                                              \
+    if(_receiver) {                                                           \
+      _SpektrumState.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    */\
+    }                                                                         \
+    _SpektrumState.Sync = 2;                                                  \
+    _SpektrumState.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(_SpektrumState.Sync == 2) {                                              \
+    _SpektrumState.HighByte = _c;                                             \
+    if (_SpektrumState.ChannelCnt == 0) {                                     \
+      _SpektrumState.SecondFrame = (_SpektrumState.HighByte & 0x80) ? 1 : 0;  \
+    }                                                                         \
+    _SpektrumState.Sync = 3;                                                  \
+    _SpektrumState.SpektrumTimer = MAX_BYTE_SPACE;                            \
+    return;                                                                   \
+  }                                                                           \
+                                                                              \
+  /* low byte of channel data */                                              \
+  if(_SpektrumState.Sync == 3) {                                              \
+    _SpektrumState.Sync = 2;                                                  \
+    _SpektrumState.SpektrumTimer = MAX_BYTE_SPACE;                            \
+    /* we overwrite the buffer now so rc data is not available now */         \
+    _SpektrumState.RcAvailable = 0;                                           \
+    ChannelData = ((uint16_t)_SpektrumState.HighByte << 8) | _c;              \
+    _SpektrumState.values[_SpektrumState.ChannelCnt                           \
+                          + (_SpektrumState.SecondFrame * 7)] = ChannelData;  \
+    _SpektrumState.ChannelCnt ++;                                             \
+  }                                                                           \
+                                                                              \
+  /* If we have a whole frame */                                              \
+  if(_SpektrumState.ChannelCnt >= SPEKTRUM_CHANNELS_PER_FRAME) {              \
+    /* how many frames did we expect ? */                                     \
+    ++_SpektrumState.FrameCnt;                                                \
+    if (_SpektrumState.FrameCnt == TmpExpFrames)                              \
+    {                                                                         \
+      /* set the rc_available_flag */                                         \
+      _SpektrumState.RcAvailable = 1;                                         \
+      _SpektrumState.FrameCnt = 0;                                            \
+    }                                                                         \
+    if(!_receiver) { /* main receiver */                                      \
+      EncodingType = TmpEncType;         /* only update on a good */          \
+      ExpectedFrames = TmpExpFrames;     /* main receiver frame   */          \
+    }                                                                         \
+    _SpektrumState.Sync = 0;                                                  \
+    _SpektrumState.ChannelCnt = 0;                                            \
+    _SpektrumState.SecondFrame = 0;                                           \
+    _SpektrumState.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_LINK_SLAVE  
+  uint8_t BestReceiver;
+  if ((PrimarySpektrumState.RcAvailable) || 
+      (SecondarySpektrumState.RcAvailable)) {
+    
+    if ((PrimarySpektrumState.RcAvailable) && 
+        (SecondarySpektrumState.RcAvailable)) {
+      BestReceiver  = (PrimarySpektrumState.LostFrameCnt 
+                       <= SecondarySpektrumState.LostFrameCnt) ? 0 : 1;
+    } else {
+      BestReceiver  = (PrimarySpektrumState.RcAvailable) ? 0 : 1;
+    }
+    PrimarySpektrumState.RcAvailable = 0;
+    SecondarySpektrumState.RcAvailable = 0;  
+
+#else   
+  if(PrimarySpektrumState.RcAvailable) {
+    PrimarySpektrumState.RcAvailable = 0;
+#endif       
+    ChannelCnt = 0;
+    for(int i = 0; (i < SPEKTRUM_CHANNELS_PER_FRAME * ExpectedFrames); i++) {
+#ifndef RADIO_CONTROL_LINK_SLAVE 
+      ChannelData = PrimarySpektrumState.values[i];
+#else                     
+      ChannelData = (!BestReceiver) ? PrimarySpektrumState.values[i] :
+                                 SecondarySpektrumState.values[i];
+#endif                
+      switch(EncodingType) {
+        case(0) : /* 10 bit */
+          ChannelNum = (ChannelData >> 10) & 0x0f; 
+          /* don't bother decoding unused channels */
+          if (ChannelNum < RADIO_CONTROL_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 < RADIO_CONTROL_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 */
+      }
+      if ((ChannelNum != 0x0F) && (ChannelNum > MaxChannelNum))
+        MaxChannelNum = ChannelNum; 
+        
+    }
+ 
+    if (ChannelCnt >= (MaxChannelNum + 1)) {
+      radio_control.frame_cpt++;                                       
+      radio_control.time_since_last_frame = 0;
+      radio_control.status = RADIO_CONTROL_OK;
+      for (int i = 0; i < (MaxChannelNum + 1); i++) {
+        radio_control.values[i] = SpektrumBuf[i];
+        if (i == 0) {
+          radio_control.values[i] += MAX_PPRZ;
+          radio_control.values[i] /= 2;
+        }
+        radio_control.values[i] *= SpektrumSigns[i];
+      }
+      (*frame_handler)();  
+    }   
+  }
+}
+
+ 
+/*****************************************************************************
+ *
+ * Initialise TIM1 to fire a IM1_UP_IRQ every 100 microseconds to provide
+ * timebase for SpektrumParser
+ *
+ 
*****************************************************************************/ 
+void SpektrumTimerInit( void ) {
+
+  /* enable TIM1 clock */
+  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
+  
+  /* TIM1 configuration */
+  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
+  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
+  /* 100 microseconds ie 0.1 millisecond */
+  TIM_TimeBaseStructure.TIM_Period = TIM_TICS_FOR_100us-1; 
+  TIM_TimeBaseStructure.TIM_Prescaler = ((AHB_CLK / TIM_FREQ_1000000) - 1);
+  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;   
+  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down; 
+  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
+  
+  /* Enable TIM1 interrupts */
+  NVIC_InitTypeDef NVIC_InitStructure;
+  
+  /* Enable and configure TIM1 IRQ channel */
+  NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure);
+  
+  /* Enable TIM1 Update interrupt */
+  TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
+  TIM_ClearFlag(TIM1, TIM_FLAG_Update); 
+  
+  /* TIM1 enable counter */
+  TIM_Cmd(TIM1, ENABLE);
+}
+
+/*****************************************************************************
+ *
+ * TIM1 interrupt request handler updates times used by SpektrumParser
+ *
+ *****************************************************************************/
+void tim1_up_irq_handler( void ) {
+  
+  TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
+  
+  if (PrimarySpektrumState.SpektrumTimer) 
+    --PrimarySpektrumState.SpektrumTimer; 
+#ifdef RADIO_CONTROL_LINK_SLAVE    
+  if (SecondarySpektrumState.SpektrumTimer) 
+    --SecondarySpektrumState.SpektrumTimer;
+#endif      
+}
+
+/*****************************************************************************
+ *
+ * Initialise the uarts for the spektrum satellite receivers 
+ *
+ *****************************************************************************/
+void SpektrumUartInit(void) {
+  /* init RCC */
+  PrimaryUart(_remap);
+  PrimaryUart(_clk)(PrimaryUart(_UartPeriph), ENABLE);;
+  //RCC_APB1PeriphClockCmd(PrimaryUart(_UartPeriph), ENABLE);
+ 
+  /* Enable USART interrupts */
+  NVIC_InitTypeDef nvic;
+  nvic.NVIC_IRQChannel = PrimaryUart(_IRQn);
+  nvic.NVIC_IRQChannelPreemptionPriority = 2;
+  nvic.NVIC_IRQChannelSubPriority = 1;
+  nvic.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&nvic);
+  /* Init GPIOS */
+  GPIO_InitTypeDef GPIO_InitStructure;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  /* Primary UART Rx pin as floating input */
+  GPIO_InitStructure.GPIO_Pin   = PrimaryUart(_RxPin); 
+  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
+  GPIO_Init(PrimaryUart(_RxPort), &GPIO_InitStructure);
+  /* Configure Primary UART */
+  USART_InitTypeDef usart;
+  usart.USART_BaudRate            = B115200;
+  usart.USART_WordLength          = USART_WordLength_8b;
+  usart.USART_StopBits            = USART_StopBits_1;
+  usart.USART_Parity              = USART_Parity_No;
+  usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+  usart.USART_Mode                = USART_Mode_Rx;
+  USART_Init(PrimaryUart(_reg), &usart);
+  /* Enable Primary UART Receive interrupts */
+  USART_ITConfig(PrimaryUart(_reg), USART_IT_RXNE, ENABLE);
+  /* Enable the Primary UART */
+  USART_Cmd(PrimaryUart(_reg), ENABLE);
+  
+  
+#ifdef RADIO_CONTROL_LINK_SLAVE  
+   /* init RCC */
+  SecondaryUart(_remap);
+  SecondaryUart(_clk)(SecondaryUart(_UartPeriph), ENABLE);
+  //RCC_APB1PeriphClockCmd(SecondaryUart(_UartPeriph), ENABLE);
+  /* Enable USART interrupts */
+  nvic.NVIC_IRQChannel = SecondaryUart(_IRQn);
+  nvic.NVIC_IRQChannelPreemptionPriority = 2;
+  nvic.NVIC_IRQChannelSubPriority = 2;
+  nvic.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&nvic);
+  /* Init GPIOS */;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  /* Secondary UART Rx pin as floating input */
+  GPIO_InitStructure.GPIO_Pin   = SecondaryUart(_RxPin); 
+  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN_FLOATING;
+  GPIO_Init(SecondaryUart(_RxPort), &GPIO_InitStructure);
+  /* Configure secondary UART */ 
+  usart.USART_BaudRate            = B115200;
+  usart.USART_WordLength          = USART_WordLength_8b;
+  usart.USART_StopBits            = USART_StopBits_1;
+  usart.USART_Parity              = USART_Parity_No;
+  usart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
+  usart.USART_Mode                = USART_Mode_Rx;
+  USART_Init(SecondaryUart(_reg), &usart);
+  /* Enable Secondary UART Receive interrupts */
+  USART_ITConfig(SecondaryUart(_reg), USART_IT_RXNE, ENABLE);
+  /* Enable the Primary UART */
+  USART_Cmd(SecondaryUart(_reg), ENABLE);
+#endif  
+  
+}
+
+/*****************************************************************************
+ *
+ * The primary receiver UART interrupt request handler which passes the 
+ * received character to Spektrum Parser.
+ *
+ *****************************************************************************/
+void PrimaryUart(_irq_handler)(void) {
+  
+  if(USART_GetITStatus(PrimaryUart(_reg), USART_IT_TXE) != RESET) {
+      USART_ITConfig(PrimaryUart(_reg), USART_IT_TXE, DISABLE);
+  }
+  
+  if(USART_GetITStatus(PrimaryUart(_reg), USART_IT_RXNE) != RESET) {
+    uint8_t b =  USART_ReceiveData(PrimaryUart(_reg));
+    SpektrumParser(b, PrimarySpektrumState, 0);      
+  }
+}
+
+/*****************************************************************************
+ *
+ * The secondary receiver UART interrupt request handler which passes the 
+ * received character to Spektrum Parser.
+ *
+ *****************************************************************************/
+#ifdef RADIO_CONTROL_LINK_SLAVE
+void SecondaryUart(_irq_handler)(void) {
+  
+  if(USART_GetITStatus(SecondaryUart(_reg), USART_IT_TXE) != RESET) {
+      USART_ITConfig(SecondaryUart(_reg), USART_IT_TXE, DISABLE);
+  }
+  
+  if(USART_GetITStatus(SecondaryUart(_reg), USART_IT_RXNE) != RESET) {
+    uint8_t b =  USART_ReceiveData(SecondaryUart(_reg));
+    SpektrumParser(b, SecondarySpektrumState, 1);       
+  }
+}
+#endif
+
+/*****************************************************************************
+ *
+ * Use pin to output debug information.
+ *
+ *****************************************************************************/
+void DebugInit(void) {
+  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE);
+  GPIO_InitTypeDef GPIO_InitStructure;
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(GPIOC, &GPIO_InitStructure);  
+  GPIO_WriteBit(GPIOC, GPIO_Pin_5 , Bit_RESET );       
+}
+
+/*****************************************************************************
+ *
+ * The following functions provide functionality to allow binding of 
+ * spektrum satellite receivers. The pulse train sent to them means
+ * that Lisa is emulating a 9 channel JR-R921 24.
+ *
+ *****************************************************************************/
+/*****************************************************************************
+ *
+ * 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) {
+  
+  /* init RCC */
   RCC_APB2PeriphClockCmd(BIND_PIN_PERIPH , ENABLE);
-  GPIO_InitTypeDef gpio;
-  gpio.GPIO_Pin = BIND_PIN;
-  gpio.GPIO_Mode = GPIO_Mode_IPU;
-  gpio.GPIO_Speed = GPIO_Speed_2MHz;
-  GPIO_Init(BIND_PIN_PORT, &gpio);
-
-  /* exit if the BIND_PIN is high, it needs to be pulled low at startup to 
initiate bind */
+  
+  /* Init GPIO for the bind pin */
+  GPIO_InitTypeDef GPIO_InitStructure;
+  GPIO_InitStructure.GPIO_Pin = BIND_PIN;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+  GPIO_Init(BIND_PIN_PORT, &GPIO_InitStructure);
+  /* exit if the BIND_PIN is high, it needs to 
+     be pulled low at startup to initiate bind */
   if (GPIO_ReadInputDataBit(BIND_PIN_PORT, BIND_PIN)) 
     return;
 
   /* bind initiated, initialise the delay timer */
-  delay_init();
+  SpektrumDelayInit();
 
   /* initialise the uarts rx pins as  GPIOS */
-  RCC_APB2PeriphClockCmd(MasterRcLink(_Periph) , ENABLE);
+  RCC_APB2PeriphClockCmd(PrimaryUart(_Periph) , ENABLE);
   /* Master receiver Rx push-pull */
-  gpio.GPIO_Pin = MasterRcLink(_RxPin);
-  gpio.GPIO_Mode = GPIO_Mode_Out_PP;
-  gpio.GPIO_Speed = GPIO_Speed_50MHz;
-  GPIO_Init(MasterRcLink(_RxPort), &gpio);
+  GPIO_InitStructure.GPIO_Pin = PrimaryUart(_RxPin);
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(PrimaryUart(_RxPort), &GPIO_InitStructure);
   /* Master receiver RX line, drive high */
-  GPIO_WriteBit(MasterRcLink(_RxPort), MasterRcLink(_RxPin) , Bit_SET );
+  GPIO_WriteBit(PrimaryUart(_RxPort), PrimaryUart(_RxPin) , Bit_SET );
 
 #ifdef RADIO_CONTROL_LINK_SLAVE
-   RCC_APB2PeriphClockCmd(SlaveRcLink(_Periph) , ENABLE);
+   RCC_APB2PeriphClockCmd(SecondaryUart(_Periph) , ENABLE);
   /* Slave receiver Rx push-pull */
-  gpio.GPIO_Pin = SlaveRcLink(_RxPin);
-  gpio.GPIO_Mode = GPIO_Mode_Out_PP;
-  gpio.GPIO_Speed = GPIO_Speed_50MHz;
-  GPIO_Init(SlaveRcLink(_RxPort), &gpio);
+  GPIO_InitStructure.GPIO_Pin = SecondaryUart(_RxPin);
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(SecondaryUart(_RxPort), &GPIO_InitStructure);
   /* Slave receiver RX line, drive high */
-  GPIO_WriteBit(SlaveRcLink(_RxPort), SlaveRcLink(_RxPin) , Bit_SET );
+  GPIO_WriteBit(SecondaryUart(_RxPort), SecondaryUart(_RxPin) , Bit_SET );
 #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 */        
-  delay_ms(73);
+  DelayMs(61);
 
   for (int i = 0; i < MASTER_RECEIVER_PULSES ; i++) 
   {
-    GPIO_WriteBit(MasterRcLink(_RxPort), MasterRcLink(_RxPin), Bit_RESET );
-    delay_us(120);
-    GPIO_WriteBit(MasterRcLink(_RxPort), MasterRcLink(_RxPin), Bit_SET );
-    delay_us(120);
+    GPIO_WriteBit(PrimaryUart(_RxPort), PrimaryUart(_RxPin), Bit_RESET );
+    DelayUs(118);
+    GPIO_WriteBit(PrimaryUart(_RxPort), PrimaryUart(_RxPin), Bit_SET );
+    DelayUs(122);
   }
   
 #ifdef RADIO_CONTROL_LINK_SLAVE
   for (int i = 0; i < SLAVE_RECEIVER_PULSES; i++) 
   {
-    GPIO_WriteBit(SlaveRcLink(_RxPort), SlaveRcLink(_RxPin), Bit_RESET );
-    delay_us(120);
-    GPIO_WriteBit(SlaveRcLink(_RxPort), SlaveRcLink(_RxPin), Bit_SET );
-    delay_us(120);
+    GPIO_WriteBit(SecondaryUart(_RxPort), SecondaryUart(_RxPin), Bit_RESET );
+    DelayUs(120);
+    GPIO_WriteBit(SecondaryUart(_RxPort), SecondaryUart(_RxPin), Bit_SET );
+    DelayUs(120);
   }
 #endif /* RADIO_CONTROL_LINK_SLAVE */
 }
 
-
-/*
- *\Functions to implement busy wait loops with micro second granularity
+/*****************************************************************************
  *
- */
-
+ * Functions to implement busy wait loops with micro second granularity
+ *
+ *****************************************************************************/
+ 
 /* set TIM1 to run at DELAY_TIM_FREQUENCY */ 
-static void delay_init( void ) {
+static void SpektrumDelayInit( void ) {
   /* Enable timer clock */
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
   /* Time base configuration */
@@ -166,23 +686,15 @@
 }
 
 /* wait busy loop, microseconds */
-static void delay_us( uint16_t uSecs ) {
+static void DelayUs( uint16_t uSecs ) {
   uint16_t start = TIM1->CNT;
   /* use 16 bit count wrap around */
   while((uint16_t)(TIM1->CNT - start) <= uSecs);
 }
 
 /* wait busy loop, milliseconds */
-static void delay_ms( uint16_t mSecs ) {
+static void DelayMs( uint16_t mSecs ) {
   for(int i = 0; i < mSecs; i++) {
-    delay_us(DELAY_TIM_FREQUENCY / 1000);
+    DelayUs(DELAY_TIM_FREQUENCY / 1000);
   }
 }
-
-
-void radio_control_impl_init(void) {
-  rc_spk_parser_status = RC_SPK_STA_UNINIT;
-  rc_spk_parser_idx = 0;
-}
-
-




reply via email to

[Prev in Thread] Current Thread [Next in Thread]