Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces 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 #include "mcu_periph/sys_time.h"
34 
35 // for timer_get_frequency
36 #include "mcu_arch.h"
37 
38 INFO("Radio-Control now follows PPRZ sign convention: this means you might need to reverese some channels in your transmitter: RollRight / PitchUp / YawRight / FullThrottle / Auto2 are positive deflections")
39 
40 // for Min macro
41 #include "std.h"
42 
43 #include BOARD_CONFIG
44 
45 #define SPEKTRUM_CHANNELS_PER_FRAME 7
46 #define MAX_SPEKTRUM_FRAMES 2
47 #define MAX_SPEKTRUM_CHANNELS 16
48 
49 #define ONE_MHZ 1000000
50 
51 /* Number of low pulses sent to satellite receivers */
52 #define MASTER_RECEIVER_PULSES 5
53 #define SLAVE_RECEIVER_PULSES 6
54 
55 #define TIM_TICS_FOR_100us 100
56 #define MIN_FRAME_SPACE 70 // 7ms
57 #define MAX_BYTE_SPACE 3 // .3ms
58 
59 #ifndef NVIC_TIM6_IRQ_PRIO
60 #define NVIC_TIM6_IRQ_PRIO 2
61 #endif
62 
63 #ifndef NVIC_TIM6_DAC_IRQ_PRIO
64 #define NVIC_TIM6_DAC_IRQ_PRIO 2
65 #endif
66 
67 
68 #ifdef NVIC_UART_IRQ_PRIO
69 #define NVIC_PRIMARY_UART_PRIO NVIC_UART_IRQ_PRIO
70 #else
71 #define NVIC_PRIMARY_UART_PRIO 2
72 #endif
73 
74 /*
75  * in the makefile we set RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT to be UARTx
76  * but in uart_hw.c the initialisation functions are
77  * defined as uartx these macros give us the glue
78  * that allows static calls at compile time
79  */
80 
81 #define __PrimaryUart(dev, _x) dev##_x
82 #define _PrimaryUart(dev, _x) __PrimaryUart(dev, _x)
83 #define PrimaryUart(_x) _PrimaryUart(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT, _x)
84 
85 #define __SecondaryUart(dev, _x) dev##_x
86 #define _SecondaryUart(dev, _x) __SecondaryUart(dev, _x)
87 #define SecondaryUart(_x) _SecondaryUart(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT, _x)
88 
100 };
101 
103 
104 SpektrumStateType PrimarySpektrumState = {1, 0, 0, 0, 0, 0, 0, 0, 0, {0}};
105 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_PRIMARY_PORT)
106 
107 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
108 PRINT_CONFIG_MSG("Using secondary spektrum receiver.")
109 PRINT_CONFIG_VAR(RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT)
110 SpektrumStateType SecondarySpektrumState = {1, 0, 0, 0, 0, 0, 0, 0, 0, {0}};
111 #else
112 PRINT_CONFIG_MSG("NOT using secondary spektrum receiver.")
113 #endif
114 
116 /* the order of the channels on a spektrum is always as follows :
117  *
118  * Throttle 0
119  * Aileron 1
120  * Elevator 2
121  * Rudder 3
122  * Gear 4
123  * Flap/Aux1 5
124  * Aux2 6
125  * Aux3 7
126  * Aux4 8
127  * Aux5 9
128  * Aux6 10
129  * Aux7 11
130  */
131 
132 /* reverse some channels to suit Paparazzi conventions */
133 /* the maximum number of channels a Spektrum can transmit is 12 */
135 
136 /* Parser state variables */
139 /* initialise the uarts used by the parser */
140 void SpektrumUartInit(void);
141 /* initialise the timer used by the parser to ensure sync */
142 void SpektrumTimerInit(void);
143 
144 void tim6_irq_handler(void);
145 
154 #ifndef RC_SET_POLARITY
155 #define RC_SET_POLARITY gpio_clear
156 #endif
157 
158 /*****************************************************************************
159 *
160 * Initialise the timer an uarts used by the Spektrum receiver subsystem
161 *
162 *****************************************************************************/
164 {
165 
166  PrimarySpektrumState.ReSync = 1;
167 
168 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
169  SecondarySpektrumState.ReSync = 1;
170 #endif
171 
172  // Set polarity to normal on boards that can change this
173 #ifdef RC_POLARITY_GPIO_PORT
176 #endif
177 
180 }
181 
182 /*****************************************************************************
183  * The bind function means that the satellite receivers believe they are
184  * connected to a 9 channel JR-R921 24 receiver thus during the bind process
185  * they try to get the transmitter to transmit at the highest resolution that
186  * it can manage. The data is contained in 16 byte packets transmitted at
187  * 115200 baud. Depending on the transmitter either 1 or 2 frames are required
188  * to contain the data for all channels. These frames are either 11ms or 22ms
189  * apart.
190  *
191  * The format of each frame for the main receiver is as follows
192  *
193  * byte1: frame loss data
194  * byte2: transmitter information
195  * byte3: and byte4: channel data
196  * byte5: and byte6: channel data
197  * byte7: and byte8: channel data
198  * byte9: and byte10: channel data
199  * byte11: and byte12: channel data
200  * byte13: and byte14: channel data
201  * byte15: and byte16: channel data
202  *
203  *
204  * The format of each frame for the secondary receiver is as follows
205  *
206  * byte1: frame loss data
207  * byte2: frame loss data
208  * byte3: and byte4: channel data
209  * byte5: and byte6: channel data
210  * byte7: and byte8: channel data
211  * byte9: and byte10: channel data
212  * byte11: and byte12: channel data
213  * byte13: and byte14: channel data
214  * byte15: and byte16: channel data
215  *
216  * The frame loss data bytes starts out containing 0 as long as the
217  * transmitter is switched on before the receivers. It then increments
218  * whenever frames are dropped.
219  *
220  * Three values for the transmitter information byte have been seen thus far
221  *
222  * 0x01 From a Spektrum DX7eu which transmits a single frame containing all
223  * channel data every 22ms with 10bit resolution.
224  *
225  * 0x02 From a Spektrum DM9 module which transmits two frames to carry the
226  * data for all channels 11ms apart with 10bit resolution.
227  *
228  * 0x12 From a Spektrum DX7se which transmits two frames to carry the
229  * data for all channels 11ms apart with 11bit resolution.
230  *
231  * 0x12 From a JR X9503 which transmits two frames to carry the
232  * data for all channels 11ms apart with 11bit resolution.
233  *
234  * 0x01 From a Spektrum DX7 which transmits a single frame containing all
235  * channel data every 22ms with 10bit resolution.
236  *
237  * 0x12 From a JR DSX12 which transmits two frames to carry the
238  * data for all channels 11ms apart with 11bit resolution.
239  *
240  * 0x1 From a Spektru DX5e which transmits a single frame containing all
241  * channel data every 22ms with 10bit resolution.
242  *
243  * 0x01 From a Spektrum DX6i which transmits a single frame containing all
244  * channel data every 22ms with 10bit resolution.
245  *
246  * Currently the assumption is that the data has the form :
247  *
248  * [0 0 0 R 0 0 N1 N0]
249  *
250  * where :
251  *
252  * 0 means a '0' bit
253  * R: 0 for 10 bit resolution 1 for 11 bit resolution channel data
254  * N1 to N0 is the number of frames required to receive all channel
255  * data.
256  *
257  * Channels can have either 10bit or 11bit resolution. Data from a tranmitter
258  * with 10 bit resolution has the form:
259  *
260  * [F 0 C3 C2 C1 C0 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0]
261  *
262  * Data from a tranmitter with 11 bit resolution has the form
263  *
264  * [F C3 C2 C1 C0 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0]
265  *
266  * where :
267  *
268  * 0 means a '0' bit
269  * F: Normally 0 but set to 1 for the first channel of the 2nd frame if a
270  * second frame is transmitted.
271  *
272  * C3 to C0 is the channel number, 4 bit, matching the numbers allocated in
273  * the transmitter.
274  *
275  * D9 to D0 is the channel data (10 bit) 0xaa..0x200..0x356 for
276  * 100% transmitter-travel
277  *
278  *
279  * D10 to D0 is the channel data (11 bit) 0x154..0x400..0x6AC for
280  * 100% transmitter-travel
281  *****************************************************************************/
282 
283 /*****************************************************************************
284 *
285 * Spektrum Parser captures frame data by using time between frames to sync on
286 *
287 *****************************************************************************/
288 
289 static inline void SpektrumParser(uint8_t _c, SpektrumStateType *spektrum_state, bool_t secondary_receiver)
290 {
291 
292  uint16_t ChannelData;
293  uint8_t TimedOut;
294  static uint8_t TmpEncType = 0; /* 0 = 10bit, 1 = 11 bit */
295  static uint8_t TmpExpFrames = 0; /* # of frames for channel data */
296 
297  TimedOut = (!spektrum_state->SpektrumTimer) ? 1 : 0;
298 
299  /* If we have just started the resync process or */
300  /* if we have recieved a character before our */
301  /* 7ms wait has finished */
302  if ((spektrum_state->ReSync == 1) ||
303  ((spektrum_state->Sync == 0) && (!TimedOut))) {
304 
305  spektrum_state->ReSync = 0;
306  spektrum_state->SpektrumTimer = MIN_FRAME_SPACE;
307  spektrum_state->Sync = 0;
308  spektrum_state->ChannelCnt = 0;
309  spektrum_state->FrameCnt = 0;
310  spektrum_state->SecondFrame = 0;
311  return;
312  }
313 
314  /* the first byte of a new frame. It was received */
315  /* more than 7ms after the last received byte. */
316  /* It represents the number of lost frames so far.*/
317  if (spektrum_state->Sync == 0) {
318  spektrum_state->LostFrameCnt = _c;
319  if (secondary_receiver) { /* secondary receiver */
320  spektrum_state->LostFrameCnt = spektrum_state->LostFrameCnt << 8;
321  }
322  spektrum_state->Sync = 1;
323  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
324  return;
325  }
326 
327  /* all other bytes should be recieved within */
328  /* MAX_BYTE_SPACE time of the last byte received */
329  /* otherwise something went wrong resynchronise */
330  if (TimedOut) {
331  spektrum_state->ReSync = 1;
332  /* next frame not expected sooner than 7ms */
333  spektrum_state->SpektrumTimer = MIN_FRAME_SPACE;
334  return;
335  }
336 
337  /* second character determines resolution and frame rate for main */
338  /* receiver or low byte of LostFrameCount for secondary receiver */
339  if (spektrum_state->Sync == 1) {
340  if (secondary_receiver) {
341  spektrum_state->LostFrameCnt += _c;
342  TmpExpFrames = ExpectedFrames;
343  } else {
345  /* protocol that is still 10 bit but without using the full range. */
346  TmpEncType = (_c & 0x10) >> 4; /* 0 = 10bit, 1 = 11 bit */
347  TmpExpFrames = _c & 0x03; /* 1 = 1 frame contains all channels */
348  /* 2 = 2 channel data in 2 frames */
349  }
350  spektrum_state->Sync = 2;
351  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
352  return;
353  }
354 
355  /* high byte of channel data if this is the first byte */
356  /* of channel data and the most significant bit is set */
357  /* then this is the second frame of channel data. */
358  if (spektrum_state->Sync == 2) {
359  spektrum_state->HighByte = _c;
360  if (spektrum_state->ChannelCnt == 0) {
361  spektrum_state->SecondFrame = (spektrum_state->HighByte & 0x80) ? 1 : 0;
362  }
363  spektrum_state->Sync = 3;
364  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
365  return;
366  }
367 
368  /* low byte of channel data */
369  if (spektrum_state->Sync == 3) {
370  spektrum_state->Sync = 2;
371  spektrum_state->SpektrumTimer = MAX_BYTE_SPACE;
372  /* we overwrite the buffer now so rc data is not available now */
373  spektrum_state->RcAvailable = 0;
374  ChannelData = ((uint16_t)spektrum_state->HighByte << 8) | _c;
375  spektrum_state->values[spektrum_state->ChannelCnt
376  + (spektrum_state->SecondFrame * 7)] = ChannelData;
377  spektrum_state->ChannelCnt ++;
378  }
379 
380  /* If we have a whole frame */
381  if (spektrum_state->ChannelCnt >= SPEKTRUM_CHANNELS_PER_FRAME) {
382  /* how many frames did we expect ? */
383  ++spektrum_state->FrameCnt;
384  if (spektrum_state->FrameCnt == TmpExpFrames) {
385  /* set the rc_available_flag */
386  spektrum_state->RcAvailable = 1;
387  spektrum_state->FrameCnt = 0;
388  }
389  if (!secondary_receiver) { /* main receiver */
390  EncodingType = TmpEncType; /* only update on a good */
391  ExpectedFrames = TmpExpFrames; /* main receiver frame */
392  }
393  spektrum_state->Sync = 0;
394  spektrum_state->ChannelCnt = 0;
395  spektrum_state->SecondFrame = 0;
396  spektrum_state->SpektrumTimer = MIN_FRAME_SPACE;
397  }
398 }
399 
400 /*****************************************************************************
401  *
402  * RadioControlEventImp decodes channel data stored by uart irq handlers
403  * and calls callback funtion
404  *
405  *****************************************************************************/
406 
407 void RadioControlEventImp(void (*frame_handler)(void))
408 {
410  uint8_t ChannelNum;
411  uint16_t ChannelData;
412  uint8_t MaxChannelNum = 0;
413 
414 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
415  /* If we have two receivers and at least one of them has new data */
416  uint8_t BestReceiver;
417  if ((PrimarySpektrumState.RcAvailable) ||
418  (SecondarySpektrumState.RcAvailable)) {
419  /* if both receivers have new data select the one */
420  /* that has had the least number of frames lost */
421  if ((PrimarySpektrumState.RcAvailable) &&
422  (SecondarySpektrumState.RcAvailable)) {
423  BestReceiver = (PrimarySpektrumState.LostFrameCnt
424  <= SecondarySpektrumState.LostFrameCnt) ? 0 : 1;
425  } else {
426  /* if only one of the receivers have new data use it */
427  BestReceiver = (PrimarySpektrumState.RcAvailable) ? 0 : 1;
428  }
429  /* clear the data ready flags */
430  PrimarySpektrumState.RcAvailable = 0;
431  SecondarySpektrumState.RcAvailable = 0;
432 
433 #else
434  /* if we have one receiver and it has new data */
435  if (PrimarySpektrumState.RcAvailable) {
436  PrimarySpektrumState.RcAvailable = 0;
437 #endif
438  ChannelCnt = 0;
439  /* for every piece of channel data we have received */
440  for (int i = 0; (i < SPEKTRUM_CHANNELS_PER_FRAME * ExpectedFrames); i++) {
441 #ifndef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
442  ChannelData = PrimarySpektrumState.values[i];
443 #else
444  ChannelData = (!BestReceiver) ? PrimarySpektrumState.values[i] :
445  SecondarySpektrumState.values[i];
446 #endif
447  /* find out the channel number and its value by */
448  /* using the EncodingType which is only received */
449  /* from the main receiver */
450  switch (EncodingType) {
451  case (0) : /* 10 bit */
452  ChannelNum = (ChannelData >> 10) & 0x0f;
453  /* don't bother decoding unused channels */
454  if (ChannelNum < SPEKTRUM_NB_CHANNEL) {
455  SpektrumBuf[ChannelNum] = ChannelData & 0x3ff;
456  SpektrumBuf[ChannelNum] -= 0x200;
457  SpektrumBuf[ChannelNum] *= MAX_PPRZ / 0x156;
458  ChannelCnt++;
459  }
460  break;
461 
462  case (1) : /* 11 bit */
463  ChannelNum = (ChannelData >> 11) & 0x0f;
464  /* don't bother decoding unused channels */
465  if (ChannelNum < SPEKTRUM_NB_CHANNEL) {
466  SpektrumBuf[ChannelNum] = ChannelData & 0x7ff;
467  SpektrumBuf[ChannelNum] -= 0x400;
468  SpektrumBuf[ChannelNum] *= MAX_PPRZ / 0x2AC;
469  ChannelCnt++;
470  }
471  break;
472 
473  default : ChannelNum = 0x0F; break; /* never going to get here */
474  }
475  /* store the value of the highest valid channel */
476  if ((ChannelNum != 0x0F) && (ChannelNum > MaxChannelNum)) {
477  MaxChannelNum = ChannelNum;
478  }
479 
480  }
481 
482  /* if we have a valid frame the pass it to the frame handler */
483  if (ChannelCnt >= (MaxChannelNum + 1)) {
487  /* since it is possible for the user use less than the actually available channels,
488  * we only transfer only Min(RADIO_CONTROL_NB_CHANNEL, available_channels)
489  */
490  for (int i = 0; i < Min(RADIO_CONTROL_NB_CHANNEL, (MaxChannelNum + 1)); i++) {
491  radio_control.values[i] = SpektrumBuf[i];
492  if (i == RADIO_THROTTLE) {
494  radio_control.values[i] /= 2;
495  }
496  radio_control.values[i] *= SpektrumSigns[i];
497  }
498  (*frame_handler)();
499  }
500  }
501 }
502 
503 
504 /*****************************************************************************
505  *
506  * Initialise TIM6 to fire an interrupt every 100 microseconds to provide
507  * timebase for SpektrumParser
508  *
509  *****************************************************************************/
511 {
512 
513  /* enable TIM6 clock */
514  rcc_periph_clock_enable(RCC_TIM6);
515 
516  /* TIM6 configuration, always counts up */
517  timer_set_mode(TIM6, TIM_CR1_CKD_CK_INT, 0, 0);
518  /* 100 microseconds ie 0.1 millisecond */
519  timer_set_period(TIM6, TIM_TICS_FOR_100us - 1);
520  uint32_t tim6_clk = timer_get_frequency(TIM6);
521  /* timer ticks with 1us */
522  timer_set_prescaler(TIM6, ((tim6_clk / ONE_MHZ) - 1));
523 
524  /* Enable TIM6 interrupts */
525 #ifdef STM32F1
526  nvic_set_priority(NVIC_TIM6_IRQ, NVIC_TIM6_IRQ_PRIO);
527  nvic_enable_irq(NVIC_TIM6_IRQ);
528 #elif defined STM32F4
529  /* the define says DAC IRQ, but it is also the global TIM6 IRQ*/
530  nvic_set_priority(NVIC_TIM6_DAC_IRQ, NVIC_TIM6_DAC_IRQ_PRIO);
531  nvic_enable_irq(NVIC_TIM6_DAC_IRQ);
532 #endif
533 
534  /* Enable TIM6 Update interrupt */
535  timer_enable_irq(TIM6, TIM_DIER_UIE);
536  timer_clear_flag(TIM6, TIM_SR_UIF);
537 
538  /* TIM6 enable counter */
539  timer_enable_counter(TIM6);
540 }
541 
542 /*****************************************************************************
543  *
544  * TIM6 interrupt request handler updates times used by SpektrumParser
545  *
546  *****************************************************************************/
547 #ifdef STM32F1
548 void tim6_isr(void)
549 {
550 #elif defined STM32F4
551 void tim6_dac_isr(void) {
552 #endif
553 
554  timer_clear_flag(TIM6, TIM_SR_UIF);
555 
556  if (PrimarySpektrumState.SpektrumTimer) {
557  --PrimarySpektrumState.SpektrumTimer;
558  }
559 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
560  if (SecondarySpektrumState.SpektrumTimer) {
561  --SecondarySpektrumState.SpektrumTimer;
562  }
563 #endif
564 }
565 
566 /*****************************************************************************
567  *
568  * Initialise the uarts for the spektrum satellite receivers
569  *
570  *****************************************************************************/
571 void SpektrumUartInit(void) {
572  /* init RCC */
574  rcc_periph_clock_enable(PrimaryUart(_RCC));
575 
576  /* Enable USART interrupts */
577  nvic_set_priority(PrimaryUart(_IRQ), NVIC_PRIMARY_UART_PRIO);
578  nvic_enable_irq(PrimaryUart(_IRQ));
579 
580  /* Init GPIOS */
581  /* Primary UART Rx pin as floating input */
583 
584  /* Configure Primary UART */
585  usart_set_baudrate(PrimaryUart(_DEV), 115200);
586  usart_set_databits(PrimaryUart(_DEV), 8);
587  usart_set_stopbits(PrimaryUart(_DEV), USART_STOPBITS_1);
588  usart_set_parity(PrimaryUart(_DEV), USART_PARITY_NONE);
589  usart_set_flow_control(PrimaryUart(_DEV), USART_FLOWCONTROL_NONE);
590  usart_set_mode(PrimaryUart(_DEV), USART_MODE_RX);
591 
592  /* Enable Primary UART Receive interrupts */
593  USART_CR1(PrimaryUart(_DEV)) |= USART_CR1_RXNEIE;
594 
595  /* Enable the Primary UART */
596  usart_enable(PrimaryUart(_DEV));
597 
598 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
599  /* init RCC */
601  rcc_periph_clock_enable(SecondaryUart(_RCC));
602 
603  /* Enable USART interrupts */
604  nvic_set_priority(SecondaryUart(_IRQ), NVIC_PRIMARY_UART_PRIO + 1);
605  nvic_enable_irq(SecondaryUart(_IRQ));
606 
607  /* Init GPIOS */;
608  /* Secondary UART Rx pin as floating input */
610 
611  /* Configure secondary UART */
612  usart_set_baudrate(SecondaryUart(_DEV), 115200);
613  usart_set_databits(SecondaryUart(_DEV), 8);
614  usart_set_stopbits(SecondaryUart(_DEV), USART_STOPBITS_1);
615  usart_set_parity(SecondaryUart(_DEV), USART_PARITY_NONE);
616  usart_set_flow_control(SecondaryUart(_DEV), USART_FLOWCONTROL_NONE);
617  usart_set_mode(SecondaryUart(_DEV), USART_MODE_RX);
618 
619  /* Enable Secondary UART Receive interrupts */
620  USART_CR1(SecondaryUart(_DEV)) |= USART_CR1_RXNEIE;
621 
622  /* Enable the Primary UART */
623  usart_enable(SecondaryUart(_DEV));
624 #endif
625 
626 }
627 
628 /*****************************************************************************
629  *
630  * The primary receiver UART interrupt request handler which passes the
631  * received character to Spektrum Parser.
632  *
633  *****************************************************************************/
634 void PrimaryUart(_ISR)(void) {
635 
636  if (((USART_CR1(PrimaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
637  ((USART_SR(PrimaryUart(_DEV)) & USART_SR_TXE) != 0)) {
638  USART_CR1(PrimaryUart(_DEV)) &= ~USART_CR1_TXEIE;
639  }
640 
641  if (((USART_CR1(PrimaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
642  ((USART_SR(PrimaryUart(_DEV)) & USART_SR_RXNE) != 0)) {
643  uint8_t b = usart_recv(PrimaryUart(_DEV));
644  SpektrumParser(b, &PrimarySpektrumState, FALSE);
645  }
646 
647 }
648 
649 /*****************************************************************************
650  *
651  * The secondary receiver UART interrupt request handler which passes the
652  * received character to Spektrum Parser.
653  *
654  *****************************************************************************/
655 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
656 void SecondaryUart(_ISR)(void) {
657 
658  if (((USART_CR1(SecondaryUart(_DEV)) & USART_CR1_TXEIE) != 0) &&
659  ((USART_SR(SecondaryUart(_DEV)) & USART_SR_TXE) != 0)) {
660  USART_CR1(SecondaryUart(_DEV)) &= ~USART_CR1_TXEIE;
661  }
662 
663  if (((USART_CR1(SecondaryUart(_DEV)) & USART_CR1_RXNEIE) != 0) &&
664  ((USART_SR(SecondaryUart(_DEV)) & USART_SR_RXNE) != 0)) {
665  uint8_t b = usart_recv(SecondaryUart(_DEV));
666  SpektrumParser(b, &SecondarySpektrumState, TRUE);
667  }
668 
669 }
670 #endif
671 
672 
673 /*****************************************************************************
674  *
675  * The following functions provide functionality to allow binding of
676  * spektrum satellite receivers. The pulse train sent to them means
677  * that AP is emulating a 9 channel JR-R921 24.
678  * By default, the same pin is used for pulse train and uart rx, but
679  * they can be different if needed
680  *
681  *****************************************************************************/
682 #ifndef SPEKTRUM_PRIMARY_BIND_CONF_PORT
683 #define SPEKTRUM_PRIMARY_BIND_CONF_PORT PrimaryUart(_BANK)
684 #endif
685 #ifndef SPEKTRUM_PRIMARY_BIND_CONF_PIN
686 #define SPEKTRUM_PRIMARY_BIND_CONF_PIN PrimaryUart(_PIN)
687 #endif
688 #ifndef SPEKTRUM_SECONDARY_BIND_CONF_PORT
689 #define SPEKTRUM_SECONDARY_BIND_CONF_PORT SecondaryUart(_BANK)
690 #endif
691 #ifndef SPEKTRUM_SECONDARY_BIND_CONF_PIN
692 #define SPEKTRUM_SECONDARY_BIND_CONF_PIN SecondaryUart(_PIN)
693 #endif
694 
695 /*****************************************************************************
696  *
697  * radio_control_spektrum_try_bind(void) must called on powerup as spektrum
698  * satellites can only bind immediately after power up also it must be called
699  * before the call to SpektrumUartInit as we leave them with their Rx pins set
700  * as outputs.
701  *
702  *****************************************************************************/
704 
705 #ifdef SPEKTRUM_BIND_PIN_HIGH
706  /* Init GPIO for the bind pin, we enable the pulldown resistor.
707  * (esden) As far as I can tell only navstick is using the PIN LOW version of
708  * the bind pin, but I assume this should not harm anything. If I am mistaken
709  * than I appologise for the inconvenience. :)
710  */
712 
713  /* exit if the BIND_PIN is low, it needs to
714  be pulled high at startup to initiate bind */
716  return;
717  }
718 #else
719  /* Init GPIO for the bind pin, we enable the pullup resistor in case we have
720  * a floating pin that does not have a hardware pullup resistor as it is the
721  * case with Lisa/M and Lisa/MX prior to version 2.1.
722  */
724 
725  /* exit if the BIND_PIN is high, it needs to
726  be pulled low at startup to initiate bind */
728  return;
729  }
730 #endif
731 
732  /* Master receiver Rx push-pull */
734 
735  /* Master receiver RX line, drive high */
737 
738 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
739  /* Slave receiver Rx push-pull */
741 
742  /* Slave receiver RX line, drive high */
744 #endif
745 
746  /* We have no idea how long the window for allowing binding after
747  power up is. This works for the moment but will need revisiting */
748  sys_time_usleep(61000);
749 
750  for (int i = 0; i < MASTER_RECEIVER_PULSES ; i++) {
752  sys_time_usleep(118);
754  sys_time_usleep(122);
755  }
756 
757 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
758  for (int i = 0; i < SLAVE_RECEIVER_PULSES; i++) {
760  sys_time_usleep(120);
762  sys_time_usleep(120);
763  }
764 #endif /* RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT */
765 
766  /* Set conf pin as input in case it is different from RX pin */
768 #ifdef RADIO_CONTROL_SPEKTRUM_SECONDARY_PORT
770 #endif
771 }
int16_t SpektrumBuf[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]
void radio_control_impl_init(void)
Definition: spektrum_arch.c:30
void gpio_setup_input_pulldown(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs with pull down resistors enabled.
unsigned short uint16_t
Definition: types.h:16
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
#define SPEKTRUM_PRIMARY_BIND_CONF_PIN
timer_clear_flag(TIM6, TIM_SR_UIF)
#define SPEKTRUM_SECONDARY_BIND_CONF_PIN
#define SLAVE_RECEIVER_PULSES
Definition: spektrum_arch.c:53
#define Min(x, y)
#define RC_POLARITY_GPIO_PIN
Definition: apogee_1.0.h:100
#define MIN_FRAME_SPACE
Definition: spektrum_arch.c:56
#define NVIC_TIM6_DAC_IRQ
CM3_WEAK tim6_dac_isr(void)
uint8_t status
Definition: radio_control.h:53
#define SPEKTRUM_SECONDARY_BIND_CONF_PORT
Some architecture independent helper functions for GPIOs.
void PrimaryUart() _ISR(void)
void SpektrumTimerInit(void)
#define MAX_SPEKTRUM_FRAMES
Definition: spektrum_arch.c:46
#define MASTER_RECEIVER_PULSES
Definition: spektrum_arch.c:52
#define SPEKTRUM_BIND_PIN
Definition: apogee_1.0.h:417
#define NVIC_TIM6_IRQ_PRIO
Definition: spektrum_arch.c:60
uint32_t timer_get_frequency(uint32_t timer_peripheral)
Get Timer clock frequency (before prescaling) Only valid if using the internal clock for the timer...
Definition: mcu_arch.c:179
pprz_t values[RADIO_CONTROL_NB_CHANNEL]
Definition: radio_control.h:58
#define PrimaryUart(_x)
Definition: spektrum_arch.c:83
static uint8_t ExpectedFrames
#define SecondaryUart(_x)
Definition: spektrum_arch.c:87
#define FALSE
Definition: std.h:5
#define TRUE
Definition: std.h:4
void gpio_set(uint32_t port, uint16_t pin)
Set a gpio output to high level.
Definition: gpio_ardrone.c:54
void tim6_irq_handler(void)
Architecture independent timing functions.
SpektrumStateType PrimarySpektrumState
#define RC_POLARITY_GPIO_PORT
Definition: apogee_1.0.h:99
#define SPEKTRUM_CHANNELS_PER_FRAME
Definition: spektrum_arch.c:45
#define SPEKTRUM_NB_CHANNEL
Definition: spektrum_arch.h:32
void gpio_clear(uint32_t port, uint16_t pin)
Clear a gpio output to low level.
Definition: gpio_ardrone.c:70
unsigned long uint32_t
Definition: types.h:18
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
signed short int16_t
Definition: types.h:17
static uint8_t EncodingType
#define NVIC_PRIMARY_UART_PRIO
Definition: spektrum_arch.c:71
struct RadioControl radio_control
Definition: radio_control.c:30
#define RADIO_THROTTLE
Definition: spektrum_arch.h:42
#define RC_SET_POLARITY
Set polarity using RC_POLARITY_GPIO.
#define RADIO_CONTROL_NB_CHANNEL
Definition: spektrum_arch.h:34
#define RC_OK
Definition: radio_control.h:48
#define SPEKTRUM_BIND_PIN_PORT
Definition: apogee_1.0.h:418
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[]
void gpio_setup_input_pullup(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs with pull up resistor enabled.
#define TIM_TICS_FOR_100us
Definition: spektrum_arch.c:55
static void sys_time_usleep(uint32_t us)
Definition: sys_time_arch.h:55
#define SPEKTRUM_PRIMARY_BIND_CONF_PORT
#define RADIO_CONTROL_SPEKTRUM_SIGNS
Definition: spektrum_arch.h:71
unsigned char uint8_t
Definition: types.h:14
void RadioControlEventImp(void(*frame_handler)(void))
Definition: spektrum_arch.c:48
void SpektrumUartInit(void)
#define NVIC_TIM6_DAC_IRQ_PRIO
Definition: spektrum_arch.c:64
void radio_control_spektrum_try_bind(void)
Definition: spektrum_arch.c:42
uint16_t gpio_get(uint32_t gpioport, uint16_t gpios)
Read a gpio value.
Definition: gpio_ardrone.c:120
void gpio_setup_input(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as inputs.
Definition: gpio_ardrone.c:86
#define MAX_BYTE_SPACE
Definition: spektrum_arch.c:57
uint8_t time_since_last_frame
Definition: radio_control.h:54
void gpio_enable_clock(uint32_t port)
Enable the relevant clock.
Definition: gpio_arch.c:34
#define MAX_PPRZ
Definition: paparazzi.h:8
signed char int8_t
Definition: types.h:15
void gpio_setup_output(uint32_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
Definition: gpio_ardrone.c:102
static void SpektrumParser(uint8_t _c, SpektrumStateType *spektrum_state, bool_t secondary_receiver)
#define ONE_MHZ
Definition: spektrum_arch.c:49
uint8_t frame_cpt
Definition: radio_control.h:57
int16_t values[SPEKTRUM_CHANNELS_PER_FRAME *MAX_SPEKTRUM_FRAMES]
Definition: spektrum_arch.c:99