Paparazzi UAS  v5.0.5_stable-7-g4b8bbb7
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
spektrum_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010 Eric Parsonage <eric@eparsonage.com>
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 #include <stdint.h>
23 #include <libopencm3/stm32/gpio.h>
24 #include <libopencm3/stm32/rcc.h>
25 #include <libopencm3/stm32/timer.h>
26 #include <libopencm3/stm32/usart.h>
27 #include <libopencm3/cm3/nvic.h>
28 
30 #include "subsystems/radio_control/spektrum_arch.h"
31 #include "mcu_periph/uart.h"
32 #include "mcu_periph/gpio.h"
33 
34 #include BOARD_CONFIG
35 
36 #define SPEKTRUM_CHANNELS_PER_FRAME 7
37 #define MAX_SPEKTRUM_FRAMES 2
38 #define MAX_SPEKTRUM_CHANNELS 16
39 
40 #define MAX_DELAY INT16_MAX
41 /* the frequency of the delay timer */
42 #define DELAY_TIM_FREQUENCY 1000000
43 /* Number of low pulses sent to satellite receivers */
44 #define MASTER_RECEIVER_PULSES 5
45 #define SLAVE_RECEIVER_PULSES 6
46 
47 #define TIM_FREQ_1000000 1000000
48 #define TIM_TICS_FOR_100us 100
49 #define MIN_FRAME_SPACE 70 // 7ms
50 #define MAX_BYTE_SPACE 3 // .3ms
51 
52 /*
53  * in the makefile we set RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT to be UARTx
54  * but in uart_hw.c the initialisation functions are
55  * defined as uartx these macros give us the glue
56  * that allows static calls at compile time
57  */
58 
59 #define __PrimaryUart(dev, _x) dev##_x
60 #define _PrimaryUart(dev, _x) __PrimaryUart(dev, _x)
61 #define PrimaryUart(_x) _PrimaryUart(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT, _x)
62 
63 #define __SecondaryUart(dev, _x) dev##_x
64 #define _SecondaryUart(dev, _x) __SecondaryUart(dev, _x)
65 #define SecondaryUart(_x) _SecondaryUart(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT, _x)
66 
78 };
79 
81 
82 SpektrumStateType PrimarySpektrumState = {1,0,0,0,0,0,0,0,0,{0}};
83 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT)
84 
85 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
86 PRINT_CONFIG_MSG("Using secondary spektrum receiver.")
87 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT)
88 SpektrumStateType SecondarySpektrumState = {1,0,0,0,0,0,0,0,0,{0}};
89 #else
90 PRINT_CONFIG_MSG("NOT using secondary spektrum receiver.")
91 #endif
92 
94 /* the order of the channels on a spektrum is always as follows :
95  *
96  * Throttle 0
97  * Aileron 1
98  * Elevator 2
99  * Rudder 3
100  * Gear 4
101  * Flap/Aux1 5
102  * Aux2 6
103  * Aux3 7
104  * Aux4 8
105  * Aux5 9
106  * Aux6 10
107  * Aux7 11
108  */
109 
110 /* reverse some channels to suit Paparazzi conventions */
111 /* the maximum number of channels a Spektrum can transmit is 12 */
113 
114 /* Parser state variables */
117 /* initialise the uarts used by the parser */
118 void SpektrumUartInit(void);
119 /* initialise the timer used by the parser to ensure sync */
120 void SpektrumTimerInit(void);
121 
122 void tim6_irq_handler(void);
123 /* wait busy loop, microseconds */
124 static void DelayUs( uint16_t uSecs );
125 /* wait busy loop, milliseconds */
126 static void DelayMs( uint16_t mSecs );
127 /* setup timer 1 for busy wait delays */
128 static void SpektrumDelayInit( void );
129 
130 
131  /*****************************************************************************
132  *
133  * Initialise the timer an uarts used by the Spektrum receiver subsystem
134  *
135  *****************************************************************************/
137 
138  PrimarySpektrumState.ReSync = 1;
139 
140 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
141  SecondarySpektrumState.ReSync = 1;
142 #endif
143 
146 }
147 
148 /*****************************************************************************
149  * The bind function means that the satellite receivers believe they are
150  * connected to a 9 channel JR-R921 24 receiver thus during the bind process
151  * they try to get the transmitter to transmit at the highest resolution that
152  * it can manage. The data is contained in 16 byte packets transmitted at
153  * 115200 baud. Depending on the transmitter either 1 or 2 frames are required
154  * to contain the data for all channels. These frames are either 11ms or 22ms
155  * apart.
156  *
157  * The format of each frame for the main receiver is as follows
158  *
159  * byte1: frame loss data
160  * byte2: transmitter information
161  * byte3: and byte4: channel data
162  * byte5: and byte6: channel data
163  * byte7: and byte8: channel data
164  * byte9: and byte10: channel data
165  * byte11: and byte12: channel data
166  * byte13: and byte14: channel data
167  * byte15: and byte16: channel data
168  *
169  *
170  * The format of each frame for the secondary receiver is as follows
171  *
172  * byte1: frame loss data
173  * byte2: frame loss data
174  * byte3: and byte4: channel data
175  * byte5: and byte6: channel data
176  * byte7: and byte8: channel data
177  * byte9: and byte10: channel data
178  * byte11: and byte12: channel data
179  * byte13: and byte14: channel data
180  * byte15: and byte16: channel data
181  *
182  * The frame loss data bytes starts out containing 0 as long as the
183  * transmitter is switched on before the receivers. It then increments
184  * whenever frames are dropped.
185  *
186  * Three values for the transmitter information byte have been seen thus far
187  *
188  * 0x01 From a Spektrum DX7eu which transmits a single frame containing all
189  * channel data every 22ms with 10bit resolution.
190  *
191  * 0x02 From a Spektrum DM9 module which transmits two frames to carry the
192  * data for all channels 11ms apart with 10bit resolution.
193  *
194  * 0x12 From a Spektrum DX7se which transmits two frames to carry the
195  * data for all channels 11ms apart with 11bit resolution.
196  *
197  * 0x12 From a JR X9503 which transmits two frames to carry the
198  * data for all channels 11ms apart with 11bit resolution.
199  *
200  * 0x01 From a Spektrum DX7 which transmits a single frame containing all
201  * channel data every 22ms with 10bit resolution.
202  *
203  * 0x12 From a JR DSX12 which transmits two frames to carry the
204  * data for all channels 11ms apart with 11bit resolution.
205  *
206  * 0x1 From a Spektru DX5e which transmits a single frame containing all
207  * channel data every 22ms with 10bit resolution.
208  *
209  * 0x01 From a Spektrum DX6i which transmits a single frame containing all
210  * channel data every 22ms with 10bit resolution.
211  *
212  * Currently the assumption is that the data has the form :
213  *
214  * [0 0 0 R 0 0 N1 N0]
215  *
216  * where :
217  *
218  * 0 means a '0' bit
219  * R: 0 for 10 bit resolution 1 for 11 bit resolution channel data
220  * N1 to N0 is the number of frames required to receive all channel
221  * data.
222  *
223  * Channels can have either 10bit or 11bit resolution. Data from a tranmitter
224  * with 10 bit resolution has the form:
225  *
226  * [F 0 C3 C2 C1 C0 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0]
227  *
228  * Data from a tranmitter with 11 bit resolution has the form
229  *
230  * [F C3 C2 C1 C0 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0]
231  *
232  * where :
233  *
234  * 0 means a '0' bit
235  * F: Normally 0 but set to 1 for the first channel of the 2nd frame if a
236  * second frame is transmitted.
237  *
238  * C3 to C0 is the channel number, 4 bit, matching the numbers allocated in
239  * the transmitter.
240  *
241  * D9 to D0 is the channel data (10 bit) 0xaa..0x200..0x356 for
242  * 100% transmitter-travel
243  *
244  *
245  * D10 to D0 is the channel data (11 bit) 0x154..0x400..0x6AC for
246  * 100% transmitter-travel
247  *****************************************************************************/
248 
249  /*****************************************************************************
250  *
251  * Spektrum Parser captures frame data by using time between frames to sync on
252  *
253  *****************************************************************************/
254 
255 static inline void SpektrumParser(uint8_t _c, SpektrumStateType* spektrum_state, bool_t secondary_receiver) {
256 
257  uint16_t ChannelData;
258  uint8_t TimedOut;
259  static uint8_t TmpEncType = 0; /* 0 = 10bit, 1 = 11 bit */
260  static uint8_t TmpExpFrames = 0; /* # of frames for channel data */
261 
262  TimedOut = (!spektrum_state->SpektrumTimer) ? 1 : 0;
263 
264  /* If we have just started the resync process or */
265  /* if we have recieved a character before our */
266  /* 7ms wait has finished */
267  if ((spektrum_state->ReSync == 1) ||
268  ((spektrum_state->Sync == 0) && (!TimedOut))) {
269 
270  spektrum_state->ReSync = 0;
271  spektrum_state->SpektrumTimer = MIN_FRAME_SPACE;
272  spektrum_state->Sync = 0;
273  spektrum_state->ChannelCnt = 0;
274  spektrum_state->FrameCnt = 0;
275  spektrum_state->SecondFrame = 0;
276  return;
277  }
278 
279  /* the first byte of a new frame. It was received */
280  /* more than 7ms after the last received byte. */
281  /* It represents the number of lost frames so far.*/
282  if (spektrum_state->Sync == 0) {
283  spektrum_state->LostFrameCnt = _c;
284  if(secondary_receiver) /* secondary receiver */
285  spektrum_state->LostFrameCnt = spektrum_state->LostFrameCnt << 8;
286  spektrum_state->Sync = 1;
287  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
288  return;
289  }
290 
291  /* all other bytes should be recieved within */
292  /* MAX_BYTE_SPACE time of the last byte received */
293  /* otherwise something went wrong resynchronise */
294  if(TimedOut) {
295  spektrum_state->ReSync = 1;
296  /* next frame not expected sooner than 7ms */
297  spektrum_state->SpektrumTimer = MIN_FRAME_SPACE;
298  return;
299  }
300 
301  /* second character determines resolution and frame rate for main */
302  /* receiver or low byte of LostFrameCount for secondary receiver */
303  if(spektrum_state->Sync == 1) {
304  if(secondary_receiver) {
305  spektrum_state->LostFrameCnt +=_c;
306  TmpExpFrames = ExpectedFrames;
307  } else {
309  /* protocol that is still 10 bit but without using the full range. */
310  TmpEncType =(_c & 0x10)>>4; /* 0 = 10bit, 1 = 11 bit */
311  TmpExpFrames = _c & 0x03; /* 1 = 1 frame contains all channels */
312  /* 2 = 2 channel data in 2 frames */
313  }
314  spektrum_state->Sync = 2;
315  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
316  return;
317  }
318 
319  /* high byte of channel data if this is the first byte */
320  /* of channel data and the most significant bit is set */
321  /* then this is the second frame of channel data. */
322  if(spektrum_state->Sync == 2) {
323  spektrum_state->HighByte = _c;
324  if (spektrum_state->ChannelCnt == 0) {
325  spektrum_state->SecondFrame = (spektrum_state->HighByte & 0x80) ? 1 : 0;
326  }
327  spektrum_state->Sync = 3;
328  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
329  return;
330  }
331 
332  /* low byte of channel data */
333  if(spektrum_state->Sync == 3) {
334  spektrum_state->Sync = 2;
335  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
336  /* we overwrite the buffer now so rc data is not available now */
337  spektrum_state->RcAvailable = 0;
338  ChannelData = ((uint16_t)spektrum_state->HighByte << 8) | _c;
339  spektrum_state->values[spektrum_state->ChannelCnt
340  + (spektrum_state->SecondFrame * 7)] = ChannelData;
341  spektrum_state->ChannelCnt ++;
342  }
343 
344  /* If we have a whole frame */
345  if(spektrum_state->ChannelCnt >= SPEKTRUM_CHANNELS_PER_FRAME) {
346  /* how many frames did we expect ? */
347  ++spektrum_state->FrameCnt;
348  if (spektrum_state->FrameCnt == TmpExpFrames)
349  {
350  /* set the rc_available_flag */
351  spektrum_state->RcAvailable = 1;
352  spektrum_state->FrameCnt = 0;
353  }
354  if(!secondary_receiver) { /* main receiver */
355  EncodingType = TmpEncType; /* only update on a good */
356  ExpectedFrames = TmpExpFrames; /* main receiver frame */
357  }
358  spektrum_state->Sync = 0;
359  spektrum_state->ChannelCnt = 0;
360  spektrum_state->SecondFrame = 0;
361  spektrum_state->SpektrumTimer = MIN_FRAME_SPACE;
362  }
363 }
364 
365 /*****************************************************************************
366  *
367  * RadioControlEventImp decodes channel data stored by uart irq handlers
368  * and calls callback funtion
369  *
370  *****************************************************************************/
371 
372 void RadioControlEventImp(void (*frame_handler)(void)) {
374  uint8_t ChannelNum;
375  uint16_t ChannelData;
376  uint8_t MaxChannelNum = 0;
377 
378 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
379  /* If we have two receivers and at least one of them has new data */
380  uint8_t BestReceiver;
381  if ((PrimarySpektrumState.RcAvailable) ||
382  (SecondarySpektrumState.RcAvailable)) {
383  /* if both receivers have new data select the one */
384  /* that has had the least number of frames lost */
385  if ((PrimarySpektrumState.RcAvailable) &&
386  (SecondarySpektrumState.RcAvailable)) {
387  BestReceiver = (PrimarySpektrumState.LostFrameCnt
388  <= SecondarySpektrumState.LostFrameCnt) ? 0 : 1;
389  } else {
390  /* if only one of the receivers have new data use it */
391  BestReceiver = (PrimarySpektrumState.RcAvailable) ? 0 : 1;
392  }
393  /* clear the data ready flags */
394  PrimarySpektrumState.RcAvailable = 0;
395  SecondarySpektrumState.RcAvailable = 0;
396 
397 #else
398  /* if we have one receiver and it has new data */
399  if(PrimarySpektrumState.RcAvailable) {
400  PrimarySpektrumState.RcAvailable = 0;
401 #endif
402  ChannelCnt = 0;
403  /* for every piece of channel data we have received */
404  for(int i = 0; (i < SPEKTRUM_CHANNELS_PER_FRAME * ExpectedFrames); i++) {
405 #ifndef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
406  ChannelData = PrimarySpektrumState.values[i];
407 #else
408  ChannelData = (!BestReceiver) ? PrimarySpektrumState.values[i] :
409  SecondarySpektrumState.values[i];
410 #endif
411  /* find out the channel number and its value by */
412  /* using the EncodingType which is only received */
413  /* from the main receiver */
414  switch(EncodingType) {
415  case(0) : /* 10 bit */
416  ChannelNum = (ChannelData >> 10) & 0x0f;
417  /* don't bother decoding unused channels */
418  if (ChannelNum < RADIO_CONTROL_NB_CHANNEL) {
419  SpektrumBuf[ChannelNum] = ChannelData & 0x3ff;
420  SpektrumBuf[ChannelNum] -= 0x200;
421  SpektrumBuf[ChannelNum] *= MAX_PPRZ/0x156;
422  ChannelCnt++;
423  }
424  break;
425 
426  case(1) : /* 11 bit */
427  ChannelNum = (ChannelData >> 11) & 0x0f;
428  /* don't bother decoding unused channels */
429  if (ChannelNum < RADIO_CONTROL_NB_CHANNEL) {
430  SpektrumBuf[ChannelNum] = ChannelData & 0x7ff;
431  SpektrumBuf[ChannelNum] -= 0x400;
432  SpektrumBuf[ChannelNum] *= MAX_PPRZ/0x2AC;
433  ChannelCnt++;
434  }
435  break;
436 
437  default : ChannelNum = 0x0F; break; /* never going to get here */
438  }
439  /* store the value of the highest valid channel */
440  if ((ChannelNum != 0x0F) && (ChannelNum > MaxChannelNum))
441  MaxChannelNum = ChannelNum;
442 
443  }
444 
445  /* if we have a valid frame the pass it to the frame handler */
446  if (ChannelCnt >= (MaxChannelNum + 1)) {
450  for (int i = 0; i < (MaxChannelNum + 1); i++) {
451  radio_control.values[i] = SpektrumBuf[i];
452  if (i == RADIO_THROTTLE ) {
454  radio_control.values[i] /= 2;
455  }
456  radio_control.values[i] *= SpektrumSigns[i];
457  }
458  (*frame_handler)();
459  }
460  }
461 }
462 
463 
464 /*****************************************************************************
465  *
466  * Initialise TIM6 to fire an interrupt every 100 microseconds to provide
467  * timebase for SpektrumParser
468  *
469  *****************************************************************************/
470 void SpektrumTimerInit( void ) {
471 
472  /* enable TIM6 clock */
473  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM6EN);
474 
475  /* TIM6 configuration */
476  timer_set_mode(TIM6, TIM_CR1_CKD_CK_INT,
477  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_DOWN);
478  /* 100 microseconds ie 0.1 millisecond */
479  timer_set_period(TIM6, TIM_TICS_FOR_100us-1);
480  timer_set_prescaler(TIM6, ((AHB_CLK / TIM_FREQ_1000000) - 1));
481 
482  /* Enable TIM6 interrupts */
483 #ifdef STM32F1
484  nvic_set_priority(NVIC_TIM6_IRQ, 2);
485  nvic_enable_irq(NVIC_TIM6_IRQ);
486 #elif defined STM32F4
487  /* the define says DAC IRQ, but it is also the global TIM6 IRQ*/
488  nvic_set_priority(NVIC_TIM6_DAC_IRQ, 2);
489  nvic_enable_irq(NVIC_TIM6_DAC_IRQ);
490 #endif
491 
492  /* Enable TIM6 Update interrupt */
493  timer_enable_irq(TIM6, TIM_DIER_UIE);
494  timer_clear_flag(TIM6, TIM_SR_UIF);
495 
496  /* TIM6 enable counter */
497  timer_enable_counter(TIM6);
498 }
499 
500 /*****************************************************************************
501  *
502  * TIM6 interrupt request handler updates times used by SpektrumParser
503  *
504  *****************************************************************************/
505 #ifdef STM32F1
506 void tim6_isr( void ) {
507 #elif defined STM32F4
508 void tim6_dac_isr( void ) {
509 #endif
510 
511  timer_clear_flag(TIM6, TIM_SR_UIF);
512 
513  if (PrimarySpektrumState.SpektrumTimer)
514  --PrimarySpektrumState.SpektrumTimer;
515 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
516  if (SecondarySpektrumState.SpektrumTimer)
517  --SecondarySpektrumState.SpektrumTimer;
518 #endif
519 }
520 
521 /*****************************************************************************
522  *
523  * Initialise the uarts for the spektrum satellite receivers
524  *
525  *****************************************************************************/
526 void SpektrumUartInit(void) {
527  /* init RCC */
529  rcc_peripheral_enable_clock(PrimaryUart(_RCC_REG), PrimaryUart(_RCC_DEV));
530 
531  /* Enable USART interrupts */
532  nvic_set_priority(PrimaryUart(_IRQ), 2);
533  nvic_enable_irq(PrimaryUart(_IRQ));
534 
535  /* Init GPIOS */
536  /* Primary UART Rx pin as floating input */
538 
539  /* Configure Primary UART */
540  usart_set_baudrate(PrimaryUart(_DEV), 115200);
541  usart_set_databits(PrimaryUart(_DEV), 8);
542  usart_set_stopbits(PrimaryUart(_DEV), USART_STOPBITS_1);
543  usart_set_parity(PrimaryUart(_DEV), USART_PARITY_NONE);
544  usart_set_flow_control(PrimaryUart(_DEV), USART_FLOWCONTROL_NONE);
545  usart_set_mode(PrimaryUart(_DEV), USART_MODE_RX);
546 
547  /* Enable Primary UART Receive interrupts */
548  USART_CR1(PrimaryUart(_DEV)) |= USART_CR1_RXNEIE;
549 
550  /* Enable the Primary UART */
551  usart_enable(PrimaryUart(_DEV));
552 
553 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
554  /* init RCC */
556  rcc_peripheral_enable_clock(SecondaryUart(_RCC_REG), SecondaryUart(_RCC_DEV));
557 
558  /* Enable USART interrupts */
559  nvic_set_priority(SecondaryUart(_IRQ), 3);
560  nvic_enable_irq(SecondaryUart(_IRQ));
561 
562  /* Init GPIOS */;
563  /* Secondary UART Rx pin as floating input */
565 
566  /* Configure secondary UART */
567  usart_set_baudrate(SecondaryUart(_DEV), 115200);
568  usart_set_databits(SecondaryUart(_DEV), 8);
569  usart_set_stopbits(SecondaryUart(_DEV), USART_STOPBITS_1);
570  usart_set_parity(SecondaryUart(_DEV), USART_PARITY_NONE);
571  usart_set_flow_control(SecondaryUart(_DEV), USART_FLOWCONTROL_NONE);
572  usart_set_mode(SecondaryUart(_DEV), USART_MODE_RX);
573 
574  /* Enable Secondary UART Receive interrupts */
575  USART_CR1(SecondaryUart(_DEV)) |= USART_CR1_RXNEIE;
576 
577  /* Enable the Primary UART */
578  usart_enable(SecondaryUart(_DEV));
579 #endif
580 
581 }
582 
583 /*****************************************************************************
584  *
585  * The primary receiver UART interrupt request handler which passes the
586  * received character to Spektrum Parser.
587  *
588  *****************************************************************************/
589 void PrimaryUart(_ISR)(void) {
590 
591  if (((USART_CR1(PrimaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
592  ((USART_SR(PrimaryUart(_DEV)) & USART_SR_TXE) != 0)) {
593  USART_CR1(PrimaryUart(_DEV)) &= ~USART_CR1_TXEIE;
594  }
595 
596  if (((USART_CR1(PrimaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
597  ((USART_SR(PrimaryUart(_DEV)) & USART_SR_RXNE) != 0)) {
598  uint8_t b = usart_recv(PrimaryUart(_DEV));
599  SpektrumParser(b, &PrimarySpektrumState, FALSE);
600  }
601 
602 }
603 
604 /*****************************************************************************
605  *
606  * The secondary receiver UART interrupt request handler which passes the
607  * received character to Spektrum Parser.
608  *
609  *****************************************************************************/
610 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
611 void SecondaryUart(_ISR)(void) {
612 
613  if (((USART_CR1(SecondaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
614  ((USART_SR(SecondaryUart(_DEV)) & USART_SR_TXE) != 0)) {
615  USART_CR1(SecondaryUart(_DEV)) &= ~USART_CR1_TXEIE;
616  }
617 
618  if (((USART_CR1(SecondaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
619  ((USART_SR(SecondaryUart(_DEV)) & USART_SR_RXNE) != 0)) {
620  uint8_t b = usart_recv(SecondaryUart(_DEV));
621  SpektrumParser(b, &SecondarySpektrumState, TRUE);
622  }
623 
624 }
625 #endif
626 
627 
628 /*****************************************************************************
629  *
630  * The following functions provide functionality to allow binding of
631  * spektrum satellite receivers. The pulse train sent to them means
632  * that Lisa is emulating a 9 channel JR-R921 24.
633  *
634  *****************************************************************************/
635 /*****************************************************************************
636  *
637  * radio_control_spektrum_try_bind(void) must called on powerup as spektrum
638  * satellites can only bind immediately after power up also it must be called
639  * before the call to SpektrumUartInit as we leave them with their Rx pins set
640  * as outputs.
641  *
642  *****************************************************************************/
644 
645  /* Init GPIO for the bind pin */
646  gpio_setup_input(SPEKTRUM_BIND_PIN_PORT, GPIO_MODE_INPUT);
647 
648  /* exit if the BIND_PIN is high, it needs to
649  be pulled low at startup to initiate bind */
650  if (gpio_get(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN) != 0)
651  return;
652 
653  /* bind initiated, initialise the delay timer */
655 
656  /* initialise the uarts rx pins as GPIOS */
658 
659  /* Master receiver Rx push-pull */
661 
662  /* Master receiver RX line, drive high */
663  gpio_set(PrimaryUart(_BANK), PrimaryUart(_PIN));
664 
665 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
666 
668 
669  /* Slave receiver Rx push-pull */
671 
672  /* Slave receiver RX line, drive high */
673  gpio_set(SecondaryUart(_BANK), SecondaryUart(_PIN));
674 #endif
675 
676  /* We have no idea how long the window for allowing binding after
677  power up is. This works for the moment but will need revisiting */
678  DelayMs(61);
679 
680  for (int i = 0; i < MASTER_RECEIVER_PULSES ; i++)
681  {
682  gpio_clear(PrimaryUart(_BANK), PrimaryUart(_PIN));
683  DelayUs(118);
684  gpio_set(PrimaryUart(_BANK), PrimaryUart(_PIN));
685  DelayUs(122);
686  }
687 
688 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
689  for (int i = 0; i < SLAVE_RECEIVER_PULSES; i++)
690  {
691  gpio_clear(SecondaryUart(_BANK), SecondaryUart(_PIN));
692  DelayUs(120);
693  gpio_set(SecondaryUart(_BANK), SecondaryUart(_PIN));
694  DelayUs(120);
695  }
696 #endif /* RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT */
697 }
698 
699 /*****************************************************************************
700  *
701  * Functions to implement busy wait loops with micro second granularity
702  *
703  *****************************************************************************/
704 
705 /* set TIM6 to run at DELAY_TIM_FREQUENCY */
706 static void SpektrumDelayInit( void ) {
707 
708  /* Enable timer clock */
709  rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM6EN);
710 
711  /* Make sure the timer is reset to default values. */
712  timer_reset(TIM6);
713 
714  /* Time base configuration */
715  /* Mode does not need to be set as the default reset values are ok. */
716  timer_set_period(TIM6, UINT16_MAX);
717  timer_set_prescaler(TIM6, (AHB_CLK / DELAY_TIM_FREQUENCY) - 1);
718 
719  /*
720  * Let's start the timer late in the cycle to force an update event before
721  * we start using this timer for generating delays. Otherwise the prescaler
722  * value does not seem to be taken over by the timer, resulting in way too
723  * high counting frequency. There does not seem to be a force update bit on
724  * TIM6 is there?
725  */
726  TIM6_CNT = 65534;
727 
728  /* Enable counter */
729  timer_enable_counter(TIM6);
730 }
731 
732 /* wait busy loop, microseconds */
733 static void DelayUs( uint16_t uSecs ) {
734  uint16_t start = TIM6_CNT;
735 
736  /* use 16 bit count wrap around */
737  while((TIM6_CNT - start) <= uSecs);
738 }
739 
740 /* wait busy loop, milliseconds */
741 static void DelayMs( uint16_t mSecs ) {
742 
743  for(int i = 0; i < mSecs; i++) {
745  }
746 }
int16_t SpektrumBuf[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]
Definition: spektrum_arch.c:93
void radio_control_impl_init(void)
Definition: spektrum_arch.c:30
#define AHB_CLK
Definition: apogee_0.99.h:8
void radio_control_spektrum_try_bind(void)
unsigned short uint16_t
Definition: types.h:16
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
timer_clear_flag(TIM6, TIM_SR_UIF)
#define SLAVE_RECEIVER_PULSES
Definition: spektrum_arch.c:45
#define MIN_FRAME_SPACE
Definition: spektrum_arch.c:49
#define DELAY_TIM_FREQUENCY
Definition: spektrum_arch.c:42
void RadioControlEventImp(void(*frame_handler)(void))
uint8_t frame_cpt
Definition: radio_control.h:54
Some architecture independent helper functions for GPIOs.
void PrimaryUart() _ISR(void)
void SpektrumTimerInit(void)
#define MAX_SPEKTRUM_FRAMES
Definition: spektrum_arch.c:37
uint8_t time_since_last_frame
Definition: radio_control.h:51
#define MASTER_RECEIVER_PULSES
Definition: spektrum_arch.c:44
void gpio_setup_output(uint32_t port, uint16_t pin)
Setup gpio pin as generic output.
#define PrimaryUart(_x)
Definition: spektrum_arch.c:61
static uint8_t ExpectedFrames
#define SecondaryUart(_x)
Definition: spektrum_arch.c:65
#define FALSE
Definition: imu_chimu.h:141
#define SPEKTRUM_BIND_PIN_PORT
Definition: apogee_0.99.h:293
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
Definition: radio_control.h:55
void tim6_irq_handler(void)
SpektrumStateType PrimarySpektrumState
Definition: spektrum_arch.c:82
#define SPEKTRUM_CHANNELS_PER_FRAME
Definition: spektrum_arch.c:36
signed short int16_t
Definition: types.h:17
static uint8_t EncodingType
#define TIM_FREQ_1000000
Definition: spektrum_arch.c:47
struct RadioControl radio_control
Definition: radio_control.c:25
int gpio_set(int nr, int val)
Definition: gpio_ardrone.c:32
void gpio_enable_clock(uint32_t port)
void gpio_setup_input(uint32_t port, uint16_t pin)
Setup a gpio pin as generic input.
static void DelayUs(uint16_t uSecs)
#define TRUE
Definition: imu_chimu.h:144
#define RC_OK
Definition: radio_control.h:45
uint8_t status
Definition: radio_control.h:50
void gpio_setup_pin_af(uint32_t port, uint16_t pin, uint8_t af, bool_t is_output)
Setup a gpio for input or output with alternate function.
int8_t SpektrumSigns[]
static void DelayMs(uint16_t mSecs)
#define RADIO_THROTTLE
Definition: spektrum_arch.h:38
#define TIM_TICS_FOR_100us
Definition: spektrum_arch.c:48
#define RADIO_CONTROL_NB_CHANNEL
Definition: spektrum_arch.h:34
#define RADIO_CONTROL_SPEKTRUM_SIGNS
Definition: spektrum_arch.h:55
unsigned char uint8_t
Definition: types.h:14
void SpektrumUartInit(void)
#define MAX_BYTE_SPACE
Definition: spektrum_arch.c:50
#define MAX_PPRZ
Definition: paparazzi.h:8
signed char int8_t
Definition: types.h:15
#define SPEKTRUM_BIND_PIN
Definition: apogee_0.99.h:292
int16_t values[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]
Definition: spektrum_arch.c:77
static void SpektrumParser(uint8_t _c, SpektrumStateType *spektrum_state, bool_t secondary_receiver)
static void SpektrumDelayInit(void)