Paparazzi UAS  v4.2.2_stable-4-gcc32f65
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
lisa_stm_gps_passthrough_main.c
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2010 The Paparazzi Team
5  *
6  * This file is part of Paparazzi.
7  *
8  * Paparazzi is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * Paparazzi is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with Paparazzi; see the file COPYING. If not, write to
20  * the Free Software Foundation, 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *
23  */
24 
25 #include "mcu.h"
26 #include "mcu_periph/sys_time.h"
27 #include "lisa/lisa_overo_link.h"
28 #include "lisa/lisa_spistream.h"
29 #include "generated/airframe.h"
30 #include "mcu_periph/uart.h"
31 #include "led.h"
32 
33 static inline void main_init(void);
34 static inline void main_periodic(void);
35 static inline void main_event(void);
36 static inline void uart_transfer_event(void);
37 
38 static inline void on_spistream_msg_received(uint8_t msg_id, uint8_t * data, uint16_t num_bytes);
39 static inline void on_spistream_msg_sent(uint8_t msg_id);
40 
41 static inline void on_overo_link_msg_received(void);
42 static inline void on_overo_link_lost(void);
43 static inline void on_overo_link_crc_failed(void);
44 
45 #ifdef SPISTREAM_DEBUG
46 static inline void uart_debug_transfer_event(void);
47 static inline void uart_debug_transfer_init(void);
48 #endif
49 
50 struct __attribute__ ((packed)) spistream_uart_msg {
51  uint8_t uart_id;
53 };
54 
55 // TODO
56 // Use 3 static instances of this struct in uart_transfer_event
57 // instead of a myriad of repetitive static vars:
58 struct uart_state {
59  struct spistream_uart_msg * msg;
65 };
66 
67 static struct spistream_uart_msg spistream_uart1_msg;
68 static struct spistream_uart_msg spistream_uart2_msg;
69 static struct spistream_uart_msg spistream_uart3_msg;
70 #ifdef SPISTREAM_DEBUG
71 static struct spistream_uart_msg spistream_debug_msg;
72 #endif
73 
74 // The number of current, unfinished spistream transfers.
75 // Incremented after sending an spistream message, decremented
76 // in spistream TX completion handler (here: on_spistream_msg_sent).
78 
79 int main(void) {
80 
81  main_init();
82 
83  while (1) {
85  main_periodic();
86  }
87  main_event();
88  }
89 
90  return 0;
91 }
92 
93 static inline void main_init(void) {
94 
95  mcu_init();
98 
99  uart1_init();
100  uart2_init();
101  uart3_init();
102 
103  spistream_uart1_msg.uart_id = 1;
104  spistream_uart2_msg.uart_id = 2;
105  spistream_uart3_msg.uart_id = 3;
106 
107 #ifdef SPISTREAM_DEBUG
108  uart_debug_transfer_init();
109 #endif
110 
113 
114 }
115 
121 static inline void on_spistream_msg_received(uint8_t msg_id,
122  uint8_t * data,
123  uint16_t num_bytes)
124 {
125  spistream_send_msg(data, num_bytes, SPISTREAM_NO_WAIT);
126 }
127 
128 static inline void on_spistream_msg_sent(uint8_t msg_id) {
131  }
132 }
133 
134 static inline void main_periodic(void)
135 {
137 
138  RunOnceEvery(1, {
139  LED_PERIODIC();
140  });
141 }
142 
153 static inline void on_overo_link_msg_received(void)
154 {
157 }
158 
159 static inline void on_overo_link_lost(void) {
160 }
161 
162 static inline void on_overo_link_crc_failed(void) {
163 }
164 
165 static inline void main_event(void)
166 {
168 
169 #ifdef SPISTREAM_DEBUG
170  uart_debug_transfer_event();
171 #else
173 #endif
174 }
175 
176 #ifdef SPISTREAM_DEBUG
177 static inline void uart_debug_transfer_init(void) {
178  uint16_t idx;
179  for(idx = 1; idx < 700; idx++) {
180  spistream_debug_msg.uart_data[idx] = idx % 40;
181  }
182 }
183 #endif
184 
192 #ifdef SPISTREAM_DEBUG
193 static inline void uart_debug_transfer_event(void) {
194  static uint16_t len = 0;
195  static uint16_t timeout = 1;
196 
197  if(timeout-- == 0) {
198  timeout = 8000;
200  {
201  LED_OFF(6);
202  len++;
203  if(len > 700) { len = 500; }
204 
205  spistream_debug_msg.uart_id = 1;
206  if(spistream_send_msg((uint8_t *)&spistream_debug_msg,
207  len+1-20,
208  SPISTREAM_WAIT_FOR_READ)) { // +1 for UART id byte
210  }
211  spistream_debug_msg.uart_id = 2;
212  if(spistream_send_msg((uint8_t *)&spistream_debug_msg,
213  len+1,
214  SPISTREAM_WAIT_FOR_READ)) { // +1 for UART id byte
216  }
217  spistream_debug_msg.uart_id = 3;
218  if(spistream_send_msg((uint8_t *)&spistream_debug_msg,
219  len+1+20,
220  SPISTREAM_WAIT_FOR_READ)) { // +1 for UART id byte
222  }
223  }
224  else {
225  LED_ON(6);
226  }
227  }
228 }
229 #endif
230 
231 static inline void uart_transfer_event(void) {
232 
233  static uint16_t uart1_num_rx_bytes = 0;
234  static uint16_t uart2_num_rx_bytes = 0;
235  static uint16_t uart3_num_rx_bytes = 0;
236  static uint32_t timeout_trig = 2;
237  static uint32_t timeout_uart1 = 0;
238  static uint32_t timeout_uart2 = 0;
239  static uint32_t timeout_uart3 = 0;
240  static uint8_t uart1_sent = 0;
241  static uint8_t uart2_sent = 0;
242  static uint8_t uart3_sent = 0;
243  static uint8_t uart1_has_data = 0;
244  static uint8_t uart2_has_data = 0;
245  static uint8_t uart3_has_data = 0;
246  static uint8_t trigger_send = 0;
247 
248  static uint8_t uart1_enabled = 1;
249  static uint8_t uart2_enabled = 1;
250  static uint8_t uart3_enabled = 1;
251 
252  // We cache data availability, so it doesn't change between checks:
253  uart1_has_data = Uart1ChAvailable();
254  uart2_has_data = Uart2ChAvailable();
255  uart3_has_data = Uart3ChAvailable();
256 
257  // Fill stage: Read data from UARTs into buffers, or increment
258  // their timeouts if no data is available:
259  if(!uart1_sent && uart1_has_data) {
260  spistream_uart1_msg.uart_data[uart1_num_rx_bytes] = Uart1Getch();
261  timeout_uart1 = 0;
262  if(uart1_num_rx_bytes < SPISTREAM_MAX_MESSAGE_LENGTH)
263  { uart1_num_rx_bytes++; }
264  } else { if(timeout_uart1 < timeout_trig) { timeout_uart1++; } }
265 
266  if(!uart2_sent && uart2_has_data) {
267  spistream_uart2_msg.uart_data[uart2_num_rx_bytes] = Uart2Getch();
268  timeout_uart2 = 0;
269  if(uart2_num_rx_bytes < SPISTREAM_MAX_MESSAGE_LENGTH)
270  { uart2_num_rx_bytes++; }
271  } else { if(timeout_uart2 < timeout_trig) { timeout_uart2++; } }
272 
273  if(!uart3_sent && uart3_has_data) {
274  spistream_uart3_msg.uart_data[uart3_num_rx_bytes] = Uart3Getch();
275  timeout_uart3 = 0;
276  if(uart3_num_rx_bytes < SPISTREAM_MAX_MESSAGE_LENGTH)
277  { uart3_num_rx_bytes++; }
278  } else { if(timeout_uart3 < timeout_trig) { timeout_uart3++; } }
279 
280  trigger_send = ((!uart1_enabled ||
281  (timeout_uart1 >= timeout_trig)) &&
282  (!uart2_enabled ||
283  (timeout_uart2 >= timeout_trig)) &&
284  (!uart3_enabled ||
285  (timeout_uart3 >= timeout_trig)));
286 
287  // Send stage: If all UART timeouts reach the timeout
288  // trigger value and have accumulated data to send
289  if(trigger_send) {
290 
291  // If there was no new data on any UART for some time
292  // and there is data in every rx buffer:
293 
295  {
296  // Warning LED: Could not finish all transactions
297  // from last call.
298  LED_ON(6);
299  }
300  else
301  {
302  LED_OFF(6);
303 
304  uart1_sent = !uart1_enabled; // If we set uartX_sent to 1 here, it
305  uart2_sent = !uart2_enabled; // is just ignored for every read poll
306  uart3_sent = !uart3_enabled; // as it seems to have been read already.
307 
308  if(!uart1_sent && uart1_num_rx_bytes > 0) {
310  uart1_num_rx_bytes+1, // +1 for UART id
312  uart1_sent = 1;
314  }
315  }
316 
317  if(!uart2_sent && uart1_num_rx_bytes > 0) {
319  uart1_num_rx_bytes+1, // +1 for UART id
321  uart2_sent = 1;
323  }
324  }
325 
326  if(!uart3_sent && uart3_num_rx_bytes > 0) {
328  uart3_num_rx_bytes+1, // +1 for UART id
330  uart3_sent = 1;
332  }
333  }
334 
335  // Transaction completed, reset state.
336  // Note: Only reset when all uart buffers have been transmitted,
337  // otherwise the timeout would start from the beginning and the
338  // loop phase shifts (aka "you're in the deep").
339  uart1_num_rx_bytes = 0;
340  uart2_num_rx_bytes = 0;
341  uart3_num_rx_bytes = 0;
342  timeout_uart1 = 0;
343  timeout_uart2 = 0;
344  timeout_uart3 = 0;
345  uart1_sent = 0;
346  uart2_sent = 0;
347  uart3_sent = 0;
348  }
349  }
350 }
unsigned short uint16_t
Definition: types.h:16
static struct spistream_uart_msg spistream_uart3_msg
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
struct __attribute__((packed))
#define SPISTREAM_MAX_MESSAGE_LENGTH
Definition: lisa_spistream.h:7
static void main_event(void)
static uint8_t spistream_send_msg(uint8_t *data, uint16_t num_bytes, enum spistream_flag)
Used from userland: Send num_bytes bytes from buffer over spistream.
#define LED_ON(i)
Definition: led_hw.h:28
static void on_overo_link_lost(void)
static void on_overo_link_crc_failed(void)
static void uart_transfer_event(void)
spistream stress test: Send big (500-700 bytes) messages with different message lengths for every cha...
#define PERIODIC_FREQUENCY
Definition: imu_aspirin2.c:54
struct spistream_uart_msg * msg
static struct spistream_uart_msg spistream_uart2_msg
Architecture independent timing functions.
static struct spistream_uart_msg spistream_uart1_msg
unsigned long uint32_t
Definition: types.h:18
static uint8_t spistream_wait_for_num_transfers
static void main_init(void)
int sys_time_register_timer(float duration, sys_time_cb cb)
Register a new system timer.
Definition: sys_time.c:35
static bool_t sys_time_check_and_ack_timer(tid_t id)
Definition: sys_time.h:90
#define LED_PERIODIC()
Definition: led_hw.h:8
arch independent mcu ( Micro Controller Unit ) utilities
unsigned char uint8_t
Definition: types.h:14
static void on_overo_link_msg_received(void)
Every SPI transfer contains exactly two packages of type AutopilotMessagePTStream, one for each direction (up: STM->Overo, down: Overo->STM).
int main(void)
static void spistream_init(spistream_message_rx_handler_t message_rx_handler, spistream_message_tx_handler_t message_tx_handler)
#define LED_OFF(i)
Definition: led_hw.h:29
arch independent LED (Light Emitting Diodes) API
static void on_spistream_msg_received(uint8_t msg_id, uint8_t *data, uint16_t num_bytes)
Handler for commands (messages from Overo->STM).
static void spistream_read_pkg(struct AutopilotMessagePTStream *pkg_in)
Read a single package into internal RX buffer.
static void spistream_write_pkg(struct AutopilotMessagePTStream *pkg_out)
Fill given SPI package with next package from TX buffer.
static void on_spistream_msg_sent(uint8_t msg_id)
static void main_periodic(void)
void mcu_init(void)
Definition: mcu.c:57