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