paparazzi-commits
[Top][All Lists]
Advanced

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

[paparazzi-commits] [6085] Add gps passthrough and spistream files


From: Allen Ibara
Subject: [paparazzi-commits] [6085] Add gps passthrough and spistream files
Date: Wed, 06 Oct 2010 05:08:38 +0000

Revision: 6085
          http://svn.sv.gnu.org/viewvc/?view=rev&root=paparazzi&revision=6085
Author:   aibara
Date:     2010-10-06 05:08:38 +0000 (Wed, 06 Oct 2010)
Log Message:
-----------
Add gps passthrough and spistream files

Added Paths:
-----------
    paparazzi3/trunk/sw/airborne/fms/fms_spistream.h
    paparazzi3/trunk/sw/airborne/fms/fms_spistream_client.c
    paparazzi3/trunk/sw/airborne/fms/fms_spistream_daemon.c
    paparazzi3/trunk/sw/airborne/fms/overo_test_gps_passthrough.c
    paparazzi3/trunk/sw/airborne/lisa/lisa_spistream.h
    paparazzi3/trunk/sw/airborne/lisa/lisa_stm_gps_passthrough_main.c

Added: paparazzi3/trunk/sw/airborne/fms/fms_spistream.h
===================================================================
--- paparazzi3/trunk/sw/airborne/fms/fms_spistream.h                            
(rev 0)
+++ paparazzi3/trunk/sw/airborne/fms/fms_spistream.h    2010-10-06 05:08:38 UTC 
(rev 6085)
@@ -0,0 +1,39 @@
+#ifndef FMS_SPISTREAM_H__
+#define FMS_SPISTREAM_H__
+
+#define CLIENT_SOCKET_PATH "./spistreamc.socket"
+#define DAEMON_SOCKET_PATH "./spistreamd.socket"
+
+#define min(a,b) ((a>b)? (b) : (a))
+
+void print_message(char prefix[], uint8_t msg_id, uint8_t * data, uint16_t 
num_bytes); 
+void print_message(char prefix[], uint8_t msg_id, uint8_t * data, uint16_t 
num_bytes) {
+/*
+       struct tm * timeinfo; 
+       time_t c_time;
+       char time_str[30];
+*/
+  uint8_t cnt; 
+       uint8_t log_bytes = num_bytes; 
+       if(log_bytes > 16) { log_bytes = 16; }
+/*
+       time(&c_time); 
+       timeinfo = localtime(&c_time);
+       strftime(time_str, 30, " %X ", timeinfo); 
+       
+  printf("%s %s bytes: %3d | id: %3d | UART%d | ", 
+                                prefix, time_str, num_bytes, msg_id, data[0]);
+*/
+  printf("%s bytes: %3d | id: %3d | UART%d | ", 
+                                prefix, num_bytes, msg_id, data[0]);
+  for(cnt = 1; cnt < log_bytes; cnt++) { 
+    printf("%02X ", data[cnt]);
+               if(cnt >= 24 && cnt % 24 == 0 && cnt+1 < log_bytes) { 
+                       printf("\n                                              
      ");
+               }
+  }
+  printf("\n");
+}
+
+#endif
+

Added: paparazzi3/trunk/sw/airborne/fms/fms_spistream_client.c
===================================================================
--- paparazzi3/trunk/sw/airborne/fms/fms_spistream_client.c                     
        (rev 0)
+++ paparazzi3/trunk/sw/airborne/fms/fms_spistream_client.c     2010-10-06 
05:08:38 UTC (rev 6085)
@@ -0,0 +1,225 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 The Paparazzi Team
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+// Socket stuff
+#include <sys/types.h>
+#include <sys/un.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+// End socket stuff
+
+#include <event.h>
+
+#include "std.h"
+#include "fms_debug.h"
+#include "fms_periodic.h"
+
+/* stuff for io processor link */
+#include "fms_spi_link.h"
+#include "fms_autopilot_msg.h"
+
+#define OVERO_ENV
+#include "lisa/lisa_spistream.h"
+#include "fms_spistream.h"
+
+
+static void parse_command_line(int argc, char** argv);
+static void main_init(void);
+static void main_exit(void);
+static void main_periodic(int my_sig_num);
+
+static int open_stream(void);
+
+static void on_kill(int signum);
+
+static int dfifo[4]; 
+static int cfifo[4]; 
+static char dfifo_files[4][40];
+static char cfifo_files[4][40];
+
+
+
+int main(int argc, char *argv[]) {
+
+  parse_command_line(argc, argv);
+  
+  main_init();
+  TRACE(TRACE_DEBUG, "%s", "Entering mainloop\n");
+
+  /* Enter our mainloop */
+       event_dispatch();
+       while(1) {
+               sleep(100);
+       }
+  
+       main_exit(); 
+
+  TRACE(TRACE_DEBUG, "%s", "leaving mainloop, goodbye!\n");
+
+  return 0;
+}
+
+static void main_periodic(int my_sig_num) {
+       uint8_t fifo_idx; 
+       uint8_t msg_id; 
+       uint16_t num_bytes; 
+       int16_t ret; 
+       static uint8_t buf[SPISTREAM_MAX_MESSAGE_LENGTH*10];
+
+       for(fifo_idx = 0; fifo_idx < 4; fifo_idx++) { 
+               // The periodic is triggered before fifo 
+               // connections have been initialized, so 
+               // check for a valid fd first: 
+               if(dfifo[fifo_idx] > 0) { 
+                       ret = read(dfifo[fifo_idx], (uint8_t *)(&num_bytes), 2);
+                       ret = read(dfifo[fifo_idx], (uint8_t *)(&msg_id), 1);
+
+                       memset(&buf, 0, SPISTREAM_MAX_MESSAGE_LENGTH); 
+                       if(num_bytes > SPISTREAM_MAX_MESSAGE_LENGTH) { 
+                               fprintf(stderr, "Warning: Message has length 
%d, but limit "
+                                                                               
                "is %d\n", 
+                                                               num_bytes, 
SPISTREAM_MAX_MESSAGE_LENGTH);
+                               num_bytes = SPISTREAM_MAX_MESSAGE_LENGTH;
+                       }
+                       ret = read(dfifo[fifo_idx], &buf, num_bytes);
+                       if(ret > 0 && ret == num_bytes) { 
+                               // Message received
+                               print_message(">> Client", msg_id, buf, 
num_bytes);
+                       }
+                       else if(ret > 0 && ret < num_bytes) { 
+                               fprintf(stderr, "Tried to read %d bytes, but 
only got %d\n", 
+                                                               num_bytes, 
ret); 
+                       }
+               }
+               else { 
+                       // FIFO file descriptor is invalid, 
+                       // retry to open it: 
+                       dfifo[fifo_idx] = open(dfifo_files[fifo_idx], O_RDONLY 
| O_NONBLOCK);
+               }
+       }
+
+}
+
+static void main_init(void) {
+
+  TRACE(TRACE_DEBUG, "%s", "Starting initialization\n");
+
+  /* Initalize the event library */
+  event_init();
+  
+  /* Initalize our \xF4 so accurate periodic timer */
+  if (fms_periodic_init(main_periodic)) {
+    TRACE(TRACE_ERROR, "%s", "failed to start periodic generator\n");
+    return; 
+  }
+
+       signal(SIGKILL, on_kill);
+       signal(SIGINT,  on_kill);
+       signal(SIGILL,  on_kill);
+       signal(SIGHUP,  on_kill);
+       signal(SIGQUIT, on_kill);
+       signal(SIGTERM, on_kill);
+       signal(SIGSEGV, on_kill);
+
+       if(!open_stream()) { 
+               fprintf(stderr, "Could not open stream, sorry\n");
+               exit(1);
+       }
+
+  TRACE(TRACE_DEBUG, "%s", "Initialization completed\n");
+}
+
+/**
+ * For every FIFO, a non-blocking connection try is called 
+ * via open(..., O_NONBLOCK). 
+ * This immediately returns a file descriptor or 0 if 
+ * the other end of the fifo is closed. 
+ * In the transmission, we check the FIFO file descriptors 
+ * and retry to open them, in case they are invalid. 
+ * You can also just open() them without O_NONBLOCK in 
+ * the client app, but the daemon should be running before 
+ * starting the client then, otherwise open() would block. 
+ *
+ * When using this strategy, we get connection 
+ * recovery for free when either daemon or client die. 
+ *
+ * After the connections are established, you can use them 
+ * for read() and write(), as well as register an event 
+ * trigger on them, like select() or libevent. 
+ * 
+ */
+static int open_stream(void) { 
+       uint8_t fifo_idx; 
+
+       strcpy(dfifo_files[0], "/tmp/spistream_d0.fifo"); // FIFOs for data
+       strcpy(dfifo_files[1], "/tmp/spistream_d1.fifo"); // (STM -> daemon -> 
client)
+       strcpy(dfifo_files[2], "/tmp/spistream_d2.fifo"); 
+       strcpy(dfifo_files[3], "/tmp/spistream_d3.fifo");
+       strcpy(cfifo_files[0], "/tmp/spistream_c0.fifo"); // FIFOs for commands
+       strcpy(cfifo_files[1], "/tmp/spistream_c1.fifo"); // (client -> daemon 
-> STM)
+       strcpy(cfifo_files[2], "/tmp/spistream_c2.fifo"); 
+       strcpy(cfifo_files[3], "/tmp/spistream_c3.fifo");
+       
+       for(fifo_idx = 0; fifo_idx < 4; fifo_idx++) { 
+               fprintf(stderr, "Open data stream %s ... \n", 
dfifo_files[fifo_idx]);
+               dfifo[fifo_idx] = open(dfifo_files[fifo_idx], O_RDONLY | 
O_NONBLOCK);
+               fprintf(stderr, " ...\n");
+       }
+
+       return 1; 
+
+       for(fifo_idx = 0; fifo_idx < 3; fifo_idx++) { 
+               fprintf(stderr, "Open command stream %s ... \n", 
cfifo_files[fifo_idx]);
+               cfifo[fifo_idx] = open(cfifo_files[fifo_idx], O_WRONLY);
+               if(cfifo[fifo_idx] < 0) { 
+                       fprintf(stderr, " failed\n");
+                       return 0; 
+               }
+       }
+       return 1; 
+}
+
+static void main_exit(void) 
+{
+       fprintf(stderr, "Bye!\n");
+}
+
+static void parse_command_line(int argc, char** argv) {
+}
+
+static void on_kill(int signum)
+{
+       fprintf(stderr, "Exiting, got signal %d\n", signum);
+       main_exit(); 
+       exit(1);
+}

Added: paparazzi3/trunk/sw/airborne/fms/fms_spistream_daemon.c
===================================================================
--- paparazzi3/trunk/sw/airborne/fms/fms_spistream_daemon.c                     
        (rev 0)
+++ paparazzi3/trunk/sw/airborne/fms/fms_spistream_daemon.c     2010-10-06 
05:08:38 UTC (rev 6085)
@@ -0,0 +1,347 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 The Paparazzi Team
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+// Socket stuff
+#include <sys/types.h>
+#include <sys/un.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+// End socket stuff
+
+#include <event.h>
+
+#include "std.h"
+#include "fms_debug.h"
+#include "fms_periodic.h"
+
+/* stuff for io processor link */
+#include "fms_spi_link.h"
+#include "fms_autopilot_msg.h"
+
+/* stuff for telemetry/datalink */
+
+#define OVERO_ENV
+#include "lisa/lisa_spistream.h"
+#include "fms_spistream.h"
+
+#define LOG_OUT stdout
+
+
+static void parse_command_line(int argc, char** argv);
+static void main_init(void);
+static void main_exit(void);
+static void main_periodic(int my_sig_num);
+static void spistream_event(void);
+
+static int open_stream(void);
+static void close_stream(void);
+
+static void on_timeout(int signum);
+static void on_kill(int signum);
+static void on_dead_pipe(int signum);
+
+static void on_spistream_msg_received(uint8_t msg_id, uint8_t * data, uint16_t 
num_bytes);
+static void on_spistream_msg_sent(uint8_t msg_id);
+
+static void send_to_client(uint8_t * data, uint16_t num_bytes, uint8_t 
fifo_idx);
+
+static uint8_t spistream_msg[123];
+
+static int dfifo[4]; 
+static int cfifo[4]; 
+static char dfifo_files[4][40];
+static char cfifo_files[4][40];
+
+
+
+int main(int argc, char *argv[]) {
+
+  parse_command_line(argc, argv);
+  
+  main_init();
+  TRACE(TRACE_DEBUG, "%s", "Entering mainloop\n");
+
+  /* Enter our mainloop */
+       event_dispatch();
+       while(1) {
+               sleep(100);
+       }
+  
+       main_exit(); 
+
+  TRACE(TRACE_DEBUG, "%s", "leaving mainloop, goodbye!\n");
+
+  return 0;
+}
+
+static void main_periodic(int my_sig_num) {
+
+       static int32_t every_100 = 1000;
+       if(every_100-- == 0) { 
+               every_100 = 1000;
+               spistream_send_msg(spistream_msg, 21, SPISTREAM_NO_WAIT);
+       }
+
+       spistream_event(); 
+}
+
+static void spistream_event() {
+
+  static struct AutopilotMessagePTStream msg_in;
+  static struct AutopilotMessagePTStream msg_out;
+  static uint8_t crc_valid; 
+
+  spistream_read_pkg(&msg_in); 
+/*
+  uint8_t cnt; 
+  static uint8_t pkg_size = sizeof(msg_in.pkg_data);
+       if(msg_out.message_cnt != 0) { 
+               printf("Package out: Size: %3d MID: %3d PCNTD: %3d | ", 
+                               pkg_size, msg_out.message_cnt, 
msg_out.package_cntd);
+               for(cnt = 0; cnt < pkg_size; cnt++) { 
+                       printf("%3d ", msg_out.pkg_data[cnt]);
+               }
+               printf("\n");
+       }
+*/
+  spi_link_send(&msg_out, sizeof(struct AutopilotMessageCRCFrame), &msg_in, 
&crc_valid);
+/*
+       if(msg_in.message_cnt != 0) { 
+               printf("PKG in (spi trx: %d): Size: %3d MID: %3d PCNTD: %3d | 
", SPISTREAM_PACKAGE_SIZE, 
+           pkg_size, msg_in.message_cnt, msg_in.package_cntd);
+               for(cnt = 0; cnt < pkg_size; cnt++) { 
+                       printf("%02X ", msg_in.pkg_data[cnt]);
+               }
+               printf("\n");
+       }
+*/
+  spistream_write_pkg(&msg_out); 
+}
+
+static void on_spistream_msg_received(uint8_t msg_id, 
+                                      uint8_t * data, 
+                                      uint16_t num_bytes) {
+       uint8_t uart; 
+       uint8_t buf[SPISTREAM_MAX_MESSAGE_LENGTH+3];
+
+       print_message("<< Daemon", msg_id, data, num_bytes); 
+
+       uart = data[0]; 
+       // Check for valid uart ID
+       if(uart >= 0 && uart <= 3) { 
+               if(msg_id > 0) {
+                       buf[0] = (uint8_t)(num_bytes & 0x00ff);
+                       buf[1] = (uint8_t)((num_bytes << 8) & 0x00ff);
+                       buf[2] = msg_id; 
+                       if(num_bytes > SPISTREAM_MAX_MESSAGE_LENGTH) { 
+                               fprintf(LOG_OUT, "Warning: Message has length 
%d, but limit "
+                         "is %d - truncating message\n", 
+                                                               num_bytes, 
SPISTREAM_MAX_MESSAGE_LENGTH);
+                               num_bytes = SPISTREAM_MAX_MESSAGE_LENGTH;
+                       }
+                       memcpy(buf+3, data, num_bytes); 
+                       send_to_client(buf, num_bytes+3, uart); 
+               }
+       }
+}
+
+static void send_to_client(uint8_t * data, uint16_t num_bytes, uint8_t 
fifo_idx)
+{
+       if(dfifo[fifo_idx] <= 0) { 
+               // No client connected to this fifo, yet
+               dfifo[fifo_idx] = open(dfifo_files[fifo_idx], O_WRONLY | 
O_NONBLOCK);
+               if(dfifo[fifo_idx] <= 0) { 
+                       fprintf(LOG_OUT, "No client for data fifo %d (%s)\n", 
+                                                       fifo_idx, 
dfifo_files[fifo_idx]); 
+                       return;
+               }
+       }
+       else { 
+               // Client connected to this fifo
+               if(write(dfifo[fifo_idx], data, num_bytes) == -1) { 
+                       fprintf(LOG_OUT, "Write error on data fifo %d\n", 
fifo_idx);
+               }
+       }       
+}
+
+static void on_spistream_msg_sent(uint8_t msg_id) { 
+//  TRACE(TRACE_DEBUG, "%s", "SPI message sent \n");
+}
+
+static void main_init(void) {
+  uint8_t byte_idx; 
+
+  TRACE(TRACE_DEBUG, "%s", "Starting initialization\n");
+
+  /* Initalize our SPI link to IO processor */
+  if (spi_link_init()) {
+    TRACE(TRACE_ERROR, "%s", "failed to open SPI link \n");
+    return;
+  }
+
+  spistream_init(&on_spistream_msg_received, 
+                 &on_spistream_msg_sent); 
+
+  for(byte_idx=1; byte_idx < 123; byte_idx++) { 
+    spistream_msg[byte_idx] = byte_idx; 
+  }
+  /* Initalize the event library */
+  event_init();
+  
+  /* Initalize our \xF4 so accurate periodic timer */
+  if (fms_periodic_init(main_periodic)) {
+    TRACE(TRACE_ERROR, "%s", "failed to start periodic generator\n");
+    return; 
+  }
+
+       signal(SIGKILL, on_kill);
+       signal(SIGINT,  on_kill);
+       signal(SIGILL,  on_kill);
+       signal(SIGHUP,  on_kill);
+       signal(SIGQUIT, on_kill);
+       signal(SIGTERM, on_kill);
+       signal(SIGSEGV, on_kill);
+       signal(SIGPIPE, on_dead_pipe);
+
+       if(!open_stream()) { 
+               fprintf(LOG_OUT, "Could not open stream, sorry\n");
+               exit(1);
+       }
+
+  TRACE(TRACE_DEBUG, "%s", "Initialization completed\n");
+}
+
+static void main_exit(void) 
+{
+       fprintf(LOG_OUT, "Closing socket\n");
+       close_stream(); 
+}
+
+static void parse_command_line(int argc, char** argv) {
+/*
+       while ((ch = getopt(argc, argv, "d:")) != -1) {
+               switch (ch) {
+               case 'd':
+                       daemon_mode = 1;
+                 break;
+               }
+       }
+*/
+}
+
+static int open_stream(void) { 
+       uint8_t fifo_idx; 
+       int ret; 
+
+       strcpy(dfifo_files[0], "/tmp/spistream_d0.fifo"); // FIFOs for data
+       strcpy(dfifo_files[1], "/tmp/spistream_d1.fifo"); // (STM -> daemon -> 
client)
+       strcpy(dfifo_files[2], "/tmp/spistream_d2.fifo"); 
+       strcpy(dfifo_files[3], "/tmp/spistream_d3.fifo");
+       strcpy(cfifo_files[0], "/tmp/spistream_c0.fifo"); // FIFOs for commands
+       strcpy(cfifo_files[1], "/tmp/spistream_c1.fifo"); // (client -> daemon 
-> STM)
+       strcpy(cfifo_files[2], "/tmp/spistream_c2.fifo"); 
+       strcpy(cfifo_files[3], "/tmp/spistream_c3.fifo");
+       
+       for(fifo_idx = 0; fifo_idx < 4; fifo_idx++) { 
+               fprintf(LOG_OUT, "Creating data stream %s ...", 
dfifo_files[fifo_idx]);
+               if((ret = mkfifo(dfifo_files[fifo_idx], 0777)) < 0) {
+                       fprintf(LOG_OUT, " failed\n");
+                       fprintf(LOG_OUT, "Could not create data fifo %d: %s\n", 
+                                                fifo_idx, 
dfifo_files[fifo_idx]);
+                       close_stream(); 
+                       return 0; 
+               }
+               else { 
+                       fprintf(LOG_OUT, " ok\n");
+                       dfifo[fifo_idx] = open(dfifo_files[fifo_idx], O_WRONLY 
| O_NONBLOCK);
+               }
+       }
+
+       for(fifo_idx = 0; fifo_idx < 4; fifo_idx++) { 
+               fprintf(LOG_OUT, "Creating command stream %s ... ", 
cfifo_files[fifo_idx]);
+               if((ret = mkfifo(cfifo_files[fifo_idx], 0777)) < 0) {
+                       fprintf(LOG_OUT, " failed\n");
+                       fprintf(LOG_OUT, "Could not create command fifo %d: 
%s\n", 
+                                                fifo_idx, 
cfifo_files[fifo_idx]);
+                       close_stream(); 
+                       return 0; 
+               }
+               else { 
+                       fprintf(LOG_OUT, " ok\n");
+                       cfifo[fifo_idx] = open(cfifo_files[fifo_idx], O_RDONLY 
| O_NONBLOCK);
+               }
+       }
+       return 1; 
+}
+
+static void close_stream(void) { 
+       uint8_t fifo_idx; 
+       fprintf(LOG_OUT, "Closing streams\n");
+       for(fifo_idx = 0; fifo_idx < 4; fifo_idx++) 
+       { 
+               if(dfifo[fifo_idx] >= 0) { 
+                       close(dfifo[fifo_idx]); 
+               }
+               unlink(dfifo_files[fifo_idx]); 
+               if(cfifo[fifo_idx] >= 0) { 
+                       close(cfifo[fifo_idx]); 
+               }
+               unlink(cfifo_files[fifo_idx]); 
+       }
+}
+
+static void on_timeout(int signum) 
+{
+       fprintf(LOG_OUT, "Timeout, stopping spistream daemon\n");
+       exit(6);
+}
+
+static void on_kill(int signum)
+{
+       fprintf(LOG_OUT, "Exiting, got signal %d\n", signum);
+       main_exit(); 
+       exit(1);
+}
+
+static void on_dead_pipe(int signum)
+{
+       uint8_t fifo_idx; 
+       fprintf(LOG_OUT, "Got SIGPIPE (signal %d)\n", signum);
+       // *Pop* goes the pipe. Looks like our client got AWOL. 
+       // Let's be nice and invalidate the file descriptors: 
+       for(fifo_idx = 0; fifo_idx < 4; fifo_idx++) {
+               close(dfifo[fifo_idx]); 
+               dfifo[fifo_idx] = -1; 
+       }
+}
+

Added: paparazzi3/trunk/sw/airborne/fms/overo_test_gps_passthrough.c
===================================================================
--- paparazzi3/trunk/sw/airborne/fms/overo_test_gps_passthrough.c               
                (rev 0)
+++ paparazzi3/trunk/sw/airborne/fms/overo_test_gps_passthrough.c       
2010-10-06 05:08:38 UTC (rev 6085)
@@ -0,0 +1,192 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 The Paparazzi Team
+ *
+ * This file is part of paparazzi.
+ *
+ * paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with paparazzi; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <event.h>
+
+#include "std.h"
+#include "fms_debug.h"
+#include "fms_periodic.h"
+
+/* stuff for io processor link */
+#include "fms_spi_link.h"
+#include "fms_autopilot_msg.h"
+
+/* stuff for telemetry/datalink */
+
+#define OVERO_ENV
+#include "lisa/lisa_spistream.h"
+
+static void parse_command_line(int argc, char** argv);
+static void main_init(void);
+static void main_periodic(int my_sig_num);
+static void spistream_event(void);
+
+static void on_spistream_msg_received(uint8_t msg_id, uint8_t * data, uint16_t 
num_bytes);
+static void on_spistream_msg_sent(void);
+
+static uint8_t spistream_msg[123];
+
+int main(int argc, char *argv[]) {
+
+  parse_command_line(argc, argv);
+  
+  main_init();
+  TRACE(TRACE_DEBUG, "%s", "Entering mainloop\n");
+
+  /* Enter our mainloop */
+       event_dispatch();
+       while(1) {
+               sleep(100);
+       }
+  
+  TRACE(TRACE_DEBUG, "%s", "leaving mainloop, goodbye!\n");
+
+  return 0;
+}
+
+static void main_periodic(int my_sig_num) {
+#if 0
+       static int32_t every_100 = 1000;
+       if(every_100-- == 0) { 
+               every_100 = 1000;
+               spistream_send_msg(spistream_msg, 21, SPISTREAM_NO_WAIT);
+/*
+               spistream_send_msg(spistream_msg, 15);
+               spistream_send_msg(spistream_msg, 25);
+*/
+       }
+#endif
+       spistream_event(); 
+}
+
+static void spistream_event() {
+
+  struct AutopilotMessagePTStream msg_in;
+  struct AutopilotMessagePTStream msg_out;
+  static uint8_t pkg_size = sizeof(msg_in.pkg_data);
+  uint8_t crc_valid; 
+  uint8_t cnt; 
+
+  spistream_write_pkg(&msg_out); 
+
+       if(msg_out.message_cnt != 0) { 
+               printf("Package out: Size: %3d MID: %3d PCNTD: %3d | ", 
+                               pkg_size, msg_out.message_cnt, 
msg_out.package_cntd);
+               for(cnt = 0; cnt < pkg_size; cnt++) { 
+                       printf("%3d ", msg_out.pkg_data[cnt]);
+               }
+               printf("\n");
+       }
+
+  spi_link_send(&msg_out, sizeof(struct AutopilotMessageCRCFrame), &msg_in, 
&crc_valid);
+/*
+       if(msg_in.message_cnt != 0) { 
+               printf("Package in:  Size: %3d MID: %3d PCNTD: %3d | ", 
+                               pkg_size, msg_in.message_cnt, 
msg_in.package_cntd);
+               for(cnt = 0; cnt < pkg_size; cnt++) { 
+                       printf("%3d ", msg_in.pkg_data[cnt]);
+               }
+               printf("\n");
+       }
+*/
+  spistream_read_pkg(&msg_in); 
+}
+
+static void on_spistream_msg_received(uint8_t msg_id, 
+                                      uint8_t * data, 
+                                      uint16_t num_bytes) {
+       static uint16_t plot_freq = 100; 
+
+       uint16_t log_bytes; 
+  uint8_t cnt; 
+       struct tm * timeinfo; 
+       time_t c_time;
+       char time_str[30];
+
+       plot_freq = 100; 
+       time(&c_time); 
+
+       timeinfo = localtime(&c_time);
+       strftime(time_str, 30, " %X ", timeinfo); 
+
+       log_bytes = num_bytes; 
+       if(log_bytes > 48) { log_bytes = 48; } 
+       printf("SPI message received: ");
+       printf("%s | Length: %3d | id: %3d | UART%d | ", time_str, num_bytes, 
msg_id, data[0]);
+       for(cnt = 1; cnt < log_bytes; cnt++) { 
+               printf("%02X ", data[cnt]);
+       }
+       printf("\n");
+}
+
+static void on_spistream_msg_sent(void) { 
+//  TRACE(TRACE_DEBUG, "%s", "SPI message sent \n");
+}
+
+static void main_init(void) {
+  uint8_t byte_idx; 
+
+  TRACE(TRACE_DEBUG, "%s", "Starting initialization\n");
+
+  /* Initalize our SPI link to IO processor */
+  if (spi_link_init()) {
+    TRACE(TRACE_ERROR, "%s", "failed to open SPI link \n");
+    return;
+  }
+
+  spistream_init(&on_spistream_msg_received, 
+                 &on_spistream_msg_sent); 
+/*
+       spistream_msg[0] = 0; 
+  for(byte_idx=1; byte_idx < 123; byte_idx += 4) { 
+    spistream_msg[byte_idx]   = 0xDE;
+    spistream_msg[byte_idx+1] = 0xAD;
+    spistream_msg[byte_idx+2] = 0xBE;
+    spistream_msg[byte_idx+3] = 0xEF;
+  }
+*/
+  for(byte_idx=1; byte_idx < 123; byte_idx++) { 
+    spistream_msg[byte_idx] = byte_idx; 
+  }
+  /* Initalize the event library */
+  event_init();
+  
+  /* Initalize our \xF4 so accurate periodic timer */
+  if (fms_periodic_init(main_periodic)) {
+    TRACE(TRACE_ERROR, "%s", "failed to start periodic generator\n");
+    return; 
+  }
+  
+  TRACE(TRACE_DEBUG, "%s", "Initialization completed\n");
+}
+
+static void parse_command_line(int argc, char** argv) {
+}

Added: paparazzi3/trunk/sw/airborne/lisa/lisa_spistream.h
===================================================================
--- paparazzi3/trunk/sw/airborne/lisa/lisa_spistream.h                          
(rev 0)
+++ paparazzi3/trunk/sw/airborne/lisa/lisa_spistream.h  2010-10-06 05:08:38 UTC 
(rev 6085)
@@ -0,0 +1,271 @@
+#ifndef SPISTREAM_PROTOCOL_H__
+#define SPISTREAM_PROTOCOL_H__
+
+#include <string.h>
+
+#ifndef SPISTREAM_MAX_MESSAGE_LENGTH
+#define SPISTREAM_MAX_MESSAGE_LENGTH 720
+#endif
+
+#ifndef SPISTREAM_MAX_RX_MESSAGE_LENGTH
+#define SPISTREAM_MAX_RX_MESSAGE_LENGTH SPISTREAM_MAX_MESSAGE_LENGTH
+#endif
+#ifndef SPISTREAM_RX_BUFFER_SIZE
+#define SPISTREAM_RX_BUFFER_SIZE SPISTREAM_MAX_RX_MESSAGE_LENGTH
+#endif
+
+#ifndef SPISTREAM_MAX_TX_MESSAGE_LENGTH
+#define SPISTREAM_MAX_TX_MESSAGE_LENGTH SPISTREAM_MAX_MESSAGE_LENGTH
+#endif
+#ifndef SPISTREAM_MAX_TX_PARALLEL_TRANSACTIONS
+#define SPISTREAM_MAX_TX_PARALLEL_TRANSACTIONS 4
+#endif
+#ifndef SPISTREAM_TX_MAX_BUFFER_PACKAGES
+#define SPISTREAM_TX_MAX_BUFFER_PACKAGES ( \
+               (SPISTREAM_MAX_TX_MESSAGE_LENGTH / \
+                       SPISTREAM_PACKAGE_SIZE) * \
+               SPISTREAM_MAX_TX_PARALLEL_TRANSACTIONS)
+#endif
+
+#define SPISTREAM_INVALID_MESSAGE_ID 0 
+
+struct spistream_state_t { 
+    uint8_t tx_message_cnt;     // message cnt of next message to be sent
+    uint8_t rx_package_cntd; 
+};
+
+struct spistream_message_range_t { 
+       uint8_t index; 
+       uint8_t size; 
+};
+
+struct spistream_buffers_t { 
+               uint16_t rx_num_packages; // number of packages in buffer
+
+               uint16_t tx_insert;       // next index for package insertion
+               uint16_t tx_read;         // next index to read package from
+               uint16_t tx_num_packages; // number of packages in buffer
+
+// RX stores data as array
+    uint8_t  rx[SPISTREAM_RX_BUFFER_SIZE]; 
+// TX stores packages
+    struct AutopilotMessagePTStream tx[SPISTREAM_TX_MAX_BUFFER_PACKAGES]; 
+};
+
+typedef void (*spistream_message_rx_handler_t)(uint8_t msg_id, uint8_t * data, 
uint16_t num_bytes);
+typedef void (*spistream_message_tx_handler_t)(uint8_t msg_id);
+struct spistream_config_t { 
+// Handler to call for processing received message
+    spistream_message_rx_handler_t message_rx_handler; 
+// Handler to call after message transmission
+    spistream_message_tx_handler_t message_tx_handler; 
+};
+
+enum spistream_flag { SPISTREAM_NO_WAIT=0, SPISTREAM_WAIT_FOR_READ };
+
+/* Function declarations */
+
+static inline void spistream_init(spistream_message_rx_handler_t 
message_rx_handler, 
+                                  spistream_message_tx_handler_t 
message_tx_handler);
+static inline void spistream_read_pkg(struct AutopilotMessagePTStream * 
pkg_in);
+static inline void spistream_write_pkg(struct AutopilotMessagePTStream * 
pkg_out);
+static inline uint8_t spistream_send_msg(uint8_t * data, uint16_t num_bytes, 
enum spistream_flag);
+
+/* Definitions */
+
+static struct spistream_state_t   spistream_state; 
+static struct spistream_buffers_t spistream_buffers; 
+static struct spistream_config_t  spistream; 
+
+static inline void spistream_init(spistream_message_rx_handler_t 
message_rx_handler, 
+                                  spistream_message_tx_handler_t 
message_tx_handler)
+{ 
+    memset(&spistream_buffers, 0, sizeof(struct spistream_buffers_t)); 
+    memset(&spistream_state,   0, sizeof(struct spistream_state_t)); 
+    spistream.message_rx_handler = message_rx_handler; 
+    spistream.message_tx_handler = message_tx_handler; 
+    spistream_buffers.rx_num_packages = 0; 
+    spistream_state.rx_package_cntd   = 0; 
+    spistream_buffers.tx_num_packages = 0; 
+}
+
+/**
+ * Read a single package into internal RX buffer. 
+ * Converts data from package domain to byte array. 
+ * After receiving a full message, the registered spistream.message_rx_handler 
+ * function is called. 
+ * Called on every SPI event. 
+ */
+static inline void spistream_read_pkg(struct AutopilotMessagePTStream * 
pkg_in) 
+{ 
+               uint8_t package_cntd;
+
+    if(pkg_in->message_cnt == SPISTREAM_INVALID_MESSAGE_ID) { 
+        return; 
+    } 
+
+               // In the last package of every message, the package_cntd is 
expected to be 
+               // negative or 0. It indicates the number of zero-bytes that 
are padded to 
+               // the end of the message to fill a package. 
+               if(pkg_in->package_cntd <= 0) { package_cntd = 1; } 
+               else { package_cntd = pkg_in->package_cntd; } 
+
+               if(pkg_in->package_cntd >= spistream_buffers.rx_num_packages) { 
+                       spistream_buffers.rx_num_packages = 
pkg_in->package_cntd;
+               }
+    
+    if(spistream_state.rx_package_cntd == 0) { // Beginning of new message
+        // Message length is first value of package countdown: 
+        spistream_buffers.rx_num_packages = package_cntd; 
+                               spistream_state.rx_package_cntd   = 
package_cntd;
+    }
+    memcpy(spistream_buffers.rx + 
+                                               
((spistream_buffers.rx_num_packages - package_cntd) * 
+                                                SPISTREAM_PACKAGE_SIZE), 
+           pkg_in->pkg_data, 
+           SPISTREAM_PACKAGE_SIZE);
+
+    if(pkg_in->package_cntd <= 0) { 
+      // Message is ready, pass to handler: 
+                       spistream.message_rx_handler(pkg_in->message_cnt,
+                                                                               
                                                         (uint8_t 
*)(spistream_buffers.rx), 
+                                                                               
                                                         
(spistream_buffers.rx_num_packages * 
+                                                                               
                                                                
SPISTREAM_PACKAGE_SIZE) + 
+                                                                               
                                                         pkg_in->package_cntd);
+                       spistream_state.rx_package_cntd = 0; 
+   } 
+}
+
+/**
+ * Fill given SPI package with next package from TX buffer. 
+ * Called on every SPI event. 
+ */
+static inline void spistream_write_pkg(struct AutopilotMessagePTStream * 
pkg_out) 
+{ 
+    if(spistream_buffers.tx_num_packages == 0) { 
+                       memset(pkg_out, 0, sizeof(struct 
AutopilotMessagePTStream));
+      pkg_out->message_cnt = SPISTREAM_INVALID_MESSAGE_ID;
+      return; 
+    } 
+
+               memcpy(pkg_out, 
+                                  spistream_buffers.tx + 
spistream_buffers.tx_read, 
+                                  sizeof(struct AutopilotMessagePTStream));
+               if(pkg_out->package_cntd <= 0) { 
+                       spistream.message_tx_handler(pkg_out->message_cnt); 
+               }
+
+               spistream_buffers.tx_read++; 
+               if(spistream_buffers.tx_read >= 
SPISTREAM_TX_MAX_BUFFER_PACKAGES) { 
+                       spistream_buffers.tx_read = 0; 
+               }
+
+               spistream_buffers.tx_num_packages--;
+}
+
+/**
+ * Enqueue given message in TX buffer. 
+ * This function is directly wrapped by spistream_send_message 
+ * at the moment. 
+ */
+static inline uint8_t spistream_enqueue_msg(uint8_t * data, 
+                                                                               
                                                                                
                uint16_t num_bytes, 
+                                                                               
                                                                                
                enum spistream_flag wait_for_read) 
+{ 
+       uint16_t pkg_idx, num_packages, num_padding; 
+       uint16_t idx; 
+       // Enough space in buffer?
+
+       if(wait_for_read == SPISTREAM_NO_WAIT || 
+                spistream_buffers.tx_num_packages+1 < 
SPISTREAM_TX_MAX_BUFFER_PACKAGES) 
+       { 
+               spistream_state.tx_message_cnt++;
+               // Message id 0 is reserved for invalid packages: 
+               if(spistream_state.tx_message_cnt == 
SPISTREAM_INVALID_MESSAGE_ID) { 
+                       spistream_state.tx_message_cnt = 1; 
+               }
+               // How many packages we need for this message: 
+               num_packages = (num_bytes / SPISTREAM_PACKAGE_SIZE); 
+               if(num_bytes % SPISTREAM_PACKAGE_SIZE != 0) { 
+                       num_packages++; 
+               } 
+               // How many zero-bytes we will have at the end of the last 
package: 
+               if(num_bytes > SPISTREAM_PACKAGE_SIZE) { 
+                       num_padding = (num_packages * SPISTREAM_PACKAGE_SIZE) - 
num_bytes;
+               }
+               else { 
+                       num_padding = SPISTREAM_PACKAGE_SIZE - num_bytes; 
+               }
+
+               pkg_idx = spistream_buffers.tx_insert; 
+
+               // Convert data to packages and add them to TX buffer: 
+               for(idx = 0; num_packages > 0; idx++) { 
+                       if(idx < num_bytes) { 
+                               spistream_buffers.tx[pkg_idx].pkg_data[idx % 
SPISTREAM_PACKAGE_SIZE] = data[idx];
+                       }
+                       else { // padding
+                               spistream_buffers.tx[pkg_idx].pkg_data[idx % 
SPISTREAM_PACKAGE_SIZE] = 0; 
+                       }
+                       // Last byte in current package: 
+                       if((idx % SPISTREAM_PACKAGE_SIZE) == 
SPISTREAM_PACKAGE_SIZE-1) { 
+
+                       // Finish configuration of current package
+                               // Last package uses field package_cntd to 
indicate the number 
+                               // of padding bytes it contains, as negative 
number: 
+                               if(num_packages == 1) { 
+                                       
spistream_buffers.tx[pkg_idx].package_cntd = -num_padding; 
+                               }
+                               else { 
+                                       
spistream_buffers.tx[pkg_idx].package_cntd = num_packages; 
+                               }
+                               spistream_buffers.tx[pkg_idx].message_cnt = 
spistream_state.tx_message_cnt; 
+
+                       // Prepare next package: 
+                               num_packages--; 
+                               // Increment insert pointer with ring buffer 
overflow: 
+                               spistream_buffers.tx_insert++;
+                               if(spistream_buffers.tx_insert >= 
SPISTREAM_TX_MAX_BUFFER_PACKAGES) { 
+                                       spistream_buffers.tx_insert = 0; 
+                               }
+                               // Continue with next package: 
+                               pkg_idx = spistream_buffers.tx_insert; 
+                               spistream_buffers.tx_num_packages++;
+                       }
+               }
+#if 0
+printf("Enqueue finished. Buffer: \n");
+               for(pkg_idx = 0; pkg_idx < spistream_buffers.tx_num_packages; 
pkg_idx++) { 
+                       printf("Package %2d | %3d |: ", pkg_idx, 
spistream_buffers.tx[pkg_idx].package_cntd); 
+                       for(idx = 0; idx < SPISTREAM_PACKAGE_SIZE; idx++) { 
+                               printf("%3d ", 
spistream_buffers.tx[pkg_idx].pkg_data[idx]);
+                       }
+                       printf("\n");
+               }
+#endif
+
+               return 1; 
+       }
+       return 0; 
+}
+
+static inline void spistream_dequeue_msg(uint8_t message_id) { 
+}
+
+/**
+ * Used from userland: Send num_bytes bytes from buffer over spistream. 
+ * Flags are: 
+ * - SPISTREAM_WAIT_FOR_READ:  Reject packages when TX buffer is full
+ *   and return 0, otherwise enqueue message and return 1. 
+ * - SPISTREAM_NO_WAIT: Overwrite data if TX buffer is full, enqueue 
+ *   message and always return 1. 
+ */
+static inline uint8_t spistream_send_msg(uint8_t * data, 
+                                                                               
                                                                           
uint16_t num_bytes, 
+                                                                               
                                                                                
 enum spistream_flag wait_for_read) 
+{
+    return spistream_enqueue_msg(data, num_bytes, wait_for_read);
+}
+
+#endif /* SPISTREAM_PROTOCOL_H__ */
+

Added: paparazzi3/trunk/sw/airborne/lisa/lisa_stm_gps_passthrough_main.c
===================================================================
--- paparazzi3/trunk/sw/airborne/lisa/lisa_stm_gps_passthrough_main.c           
                (rev 0)
+++ paparazzi3/trunk/sw/airborne/lisa/lisa_stm_gps_passthrough_main.c   
2010-10-06 05:08:38 UTC (rev 6085)
@@ -0,0 +1,349 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2010 The Paparazzi Team
+ *
+ * This file is part of Paparazzi.
+ *
+ * Paparazzi is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * Paparazzi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Paparazzi; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "init_hw.h"
+#include "sys_time.h"
+#include "lisa/lisa_overo_link.h"
+#include "lisa/lisa_spistream.h"
+#include "airframe.h"
+#include "uart.h"
+
+static inline void main_init(void);
+static inline void main_periodic(void);
+static inline void main_event(void);
+static inline void uart_transfer_event(void);
+
+static inline void on_spistream_msg_received(uint8_t msg_id, uint8_t * data, 
uint16_t num_bytes);
+static inline void on_spistream_msg_sent(uint8_t msg_id);
+
+static inline void on_overo_link_msg_received(void);
+static inline void on_overo_link_lost(void);
+static inline void on_overo_link_crc_failed(void);
+
+#ifdef SPISTREAM_DEBUG
+static inline void uart_debug_transfer_event(void); 
+static inline void uart_debug_transfer_init(void); 
+#endif
+
+struct __attribute__ ((packed)) spistream_uart_msg {
+  uint8_t uart_id; 
+  uint8_t uart_data[SPISTREAM_MAX_MESSAGE_LENGTH];
+};
+
+// TODO 
+// Use 3 static instances of this struct in uart_transfer_event 
+// instead of a myriad of repetitive static vars:
+struct uart_state { 
+       struct spistream_uart_msg * msg; 
+       uint32_t timeout; 
+       uint32_t num_rx_bytes; 
+       uint8_t enabled; 
+       uint8_t has_data; 
+       uint8_t sent; 
+};
+
+static struct spistream_uart_msg spistream_uart1_msg;
+static struct spistream_uart_msg spistream_uart2_msg;
+static struct spistream_uart_msg spistream_uart3_msg;
+#ifdef SPISTREAM_DEBUG
+static struct spistream_uart_msg spistream_debug_msg;
+#endif
+
+// The number of current, unfinished spistream transfers. 
+// Incremented after sending an spistream message, decremented 
+// in spistream TX completion handler (here: on_spistream_msg_sent). 
+static uint8_t spistream_wait_for_num_transfers = 0; 
+
+int main(void) {
+
+  main_init();
+
+  while (1) {
+    if (sys_time_periodic()) {
+      main_periodic();
+    }
+    main_event();
+  }
+  
+  return 0;
+}
+
+static inline void main_init(void) {
+
+  hw_init();
+  sys_time_init();
+  overo_link_init();
+
+  uart1_init(); 
+  uart2_init(); 
+  uart3_init(); 
+
+  spistream_uart1_msg.uart_id = 1; 
+  spistream_uart2_msg.uart_id = 2; 
+  spistream_uart3_msg.uart_id = 3; 
+
+#ifdef SPISTREAM_DEBUG
+       uart_debug_transfer_init(); 
+#endif
+
+  spistream_init(&on_spistream_msg_received, 
+                 &on_spistream_msg_sent);
+
+}
+
+/**
+ * Handler for commands (messages from Overo->STM). 
+ * Right now, it is just sending the command back for 
+ * debugging purposes. 
+ */
+static inline void on_spistream_msg_received(uint8_t msg_id, 
+                                             uint8_t * data, 
+                                             uint16_t num_bytes) 
+{ 
+       spistream_send_msg(data, num_bytes, SPISTREAM_NO_WAIT); 
+}
+
+static inline void on_spistream_msg_sent(uint8_t msg_id) { 
+       if(spistream_wait_for_num_transfers > 0) { 
+       spistream_wait_for_num_transfers--;
+       }
+}
+
+static inline void main_periodic(void) 
+{
+  OveroLinkPeriodic(on_overo_link_lost);
+
+  RunOnceEvery(1, {
+      LED_PERIODIC(); 
+  });
+}
+
+/**
+ * Every SPI transfer contains exactly two packages of type 
+ * AutopilotMessagePTStream, one for each direction 
+ * (up: STM->Overo, down: Overo->STM). 
+ * As we delegate SPI message handling to spistream, the SPI 
+ * event just passes both packages to 
+ * spistream_read_pkg(down_pkg) and spistream_write_pkg(up_pkg). 
+ * Apart from that, we just don't care about the SPI driver 
+ * itself. 
+ */
+static inline void on_overo_link_msg_received(void) 
+{
+  spistream_read_pkg(&overo_link.down.msg);
+  spistream_write_pkg(&overo_link.up.msg); 
+}
+
+static inline void on_overo_link_lost(void) {
+}
+
+static inline void on_overo_link_crc_failed(void) {
+}
+
+static inline void main_event(void) 
+{
+  OveroLinkEvent(on_overo_link_msg_received, on_overo_link_crc_failed);
+
+#ifdef SPISTREAM_DEBUG
+       uart_debug_transfer_event(); 
+#else
+       uart_transfer_event(); 
+#endif
+}
+
+#ifdef SPISTREAM_DEBUG
+static inline void uart_debug_transfer_init(void) { 
+       uint16_t idx; 
+       for(idx = 1; idx < 700; idx++) { 
+               spistream_debug_msg.uart_data[idx] = idx % 40; 
+       }
+}
+#endif
+
+/**
+ * spistream stress test: Send big (500-700 bytes) messages 
+ * with different message lengths for every channel and 
+ * length varying in every message. 
+ * Fool around with timeout to increase/decrease message 
+ * rate to see when it can't keep up any more. 
+ */
+#ifdef SPISTREAM_DEBUG
+static inline void uart_debug_transfer_event(void) { 
+       static uint16_t len = 0; 
+       static uint16_t timeout = 1; 
+
+       if(timeout-- == 0) {  
+               timeout = 8000; 
+               if(spistream_wait_for_num_transfers == 0) 
+               { 
+                       LED_OFF(6);
+                       len++; 
+                       if(len > 700) { len = 500; } 
+
+                       spistream_debug_msg.uart_id = 1; 
+                       if(spistream_send_msg((uint8_t *)&spistream_debug_msg, 
+                                                                               
                                len+1-20, 
+                                                                               
                                SPISTREAM_WAIT_FOR_READ)) { // +1 for UART id 
byte
+                               spistream_wait_for_num_transfers++; 
+                       }
+                       spistream_debug_msg.uart_id = 2; 
+                       if(spistream_send_msg((uint8_t *)&spistream_debug_msg, 
+                                                                               
                                len+1, 
+                                                                               
                                SPISTREAM_WAIT_FOR_READ)) { // +1 for UART id 
byte
+                               spistream_wait_for_num_transfers++; 
+                       }
+                       spistream_debug_msg.uart_id = 3; 
+                       if(spistream_send_msg((uint8_t *)&spistream_debug_msg, 
+                                                                               
                                len+1+20, 
+                                                                               
                                SPISTREAM_WAIT_FOR_READ)) { // +1 for UART id 
byte
+                               spistream_wait_for_num_transfers++; 
+                       }
+               }
+               else { 
+                       LED_ON(6);
+               }
+       }
+}
+#endif
+
+static inline void uart_transfer_event(void) { 
+
+  static uint16_t uart1_num_rx_bytes = 0; 
+  static uint16_t uart2_num_rx_bytes = 0; 
+  static uint16_t uart3_num_rx_bytes = 0; 
+  static uint32_t timeout_trig  = 2; 
+  static uint32_t timeout_uart1 = 0; 
+  static uint32_t timeout_uart2 = 0; 
+  static uint32_t timeout_uart3 = 0; 
+  static uint8_t uart1_sent = 0; 
+  static uint8_t uart2_sent = 0; 
+  static uint8_t uart3_sent = 0; 
+  static uint8_t uart1_has_data = 0; 
+  static uint8_t uart2_has_data = 0; 
+  static uint8_t uart3_has_data = 0; 
+  static uint8_t trigger_send = 0; 
+
+       static uint8_t uart1_enabled = 1; 
+       static uint8_t uart2_enabled = 1; 
+       static uint8_t uart3_enabled = 1; 
+
+  // We cache data availability, so it doesn't change between checks: 
+  uart1_has_data = Uart1ChAvailable();
+  uart2_has_data = Uart2ChAvailable();
+  uart3_has_data = Uart3ChAvailable();
+
+       // Fill stage: Read data from UARTs into buffers, or increment 
+       // their timeouts if no data is available: 
+       if(!uart1_sent && uart1_has_data) { 
+               spistream_uart1_msg.uart_data[uart1_num_rx_bytes] = 
Uart1Getch();
+               timeout_uart1 = 0; 
+               if(uart1_num_rx_bytes < SPISTREAM_MAX_MESSAGE_LENGTH) 
+                       { uart1_num_rx_bytes++; }
+       } else { if(timeout_uart1 < timeout_trig) { timeout_uart1++; } }
+       
+       if(!uart2_sent && uart2_has_data) { 
+               spistream_uart2_msg.uart_data[uart2_num_rx_bytes] = 
Uart2Getch();
+               timeout_uart2 = 0; 
+               if(uart2_num_rx_bytes < SPISTREAM_MAX_MESSAGE_LENGTH) 
+                       { uart2_num_rx_bytes++; }
+       } else { if(timeout_uart2 < timeout_trig) { timeout_uart2++; } }
+
+       if(!uart3_sent && uart3_has_data) { 
+               spistream_uart3_msg.uart_data[uart3_num_rx_bytes] = 
Uart3Getch();
+               timeout_uart3 = 0; 
+               if(uart3_num_rx_bytes < SPISTREAM_MAX_MESSAGE_LENGTH) 
+                       { uart3_num_rx_bytes++; }
+       } else { if(timeout_uart3 < timeout_trig) { timeout_uart3++; } }
+
+       trigger_send = ((!uart1_enabled || 
+                                                                       
(timeout_uart1 >= timeout_trig)) &&
+                                                                
(!uart2_enabled || 
+                                                                       
(timeout_uart2 >= timeout_trig)) &&
+                                                                
(!uart3_enabled || 
+                                                                       
(timeout_uart3 >= timeout_trig)));
+
+       // Send stage: If all UART timeouts reach the timeout 
+       // trigger value and have accumulated data to send
+       if(trigger_send) {
+
+    // If there was no new data on any UART for some time 
+    // and there is data in every rx buffer: 
+
+               if(spistream_wait_for_num_transfers > 0) 
+               { 
+                       // Warning LED: Could not finish all transactions 
+                       // from last call. 
+                       LED_ON(6); 
+               } 
+               else 
+               {
+                       LED_OFF(6);
+
+                       uart1_sent = !uart1_enabled; // If we set uartX_sent to 
1 here, it 
+                       uart2_sent = !uart2_enabled; // is just ignored for 
every read poll
+                       uart3_sent = !uart3_enabled; // as it seems to have 
been read already. 
+
+      if(!uart1_sent && uart1_num_rx_bytes > 0) { 
+                               if(spistream_send_msg((uint8_t 
*)&spistream_uart1_msg, 
+                                                                               
                  uart1_num_rx_bytes+1, // +1 for UART id
+                                                                               
                                        SPISTREAM_WAIT_FOR_READ)) { 
+                                        uart1_sent = 1; 
+                                        spistream_wait_for_num_transfers++; 
+                                }
+                       }
+
+      if(!uart2_sent && uart1_num_rx_bytes > 0) { 
+                               if(spistream_send_msg((uint8_t 
*)&spistream_uart2_msg, 
+                                                                               
                        uart1_num_rx_bytes+1, // +1 for UART id
+                                                                               
                                        SPISTREAM_WAIT_FOR_READ)) { 
+                                        uart2_sent = 1; 
+                                        spistream_wait_for_num_transfers++; 
+                               }
+                       }
+
+      if(!uart3_sent && uart3_num_rx_bytes > 0) { 
+                               if(spistream_send_msg((uint8_t 
*)&spistream_uart3_msg, 
+                                                                               
                                        uart3_num_rx_bytes+1, // +1 for UART id
+                                                                               
                                        SPISTREAM_WAIT_FOR_READ)) { 
+                                       uart3_sent = 1; 
+                                       spistream_wait_for_num_transfers++; 
+                               }
+                       }
+
+                       // Transaction completed, reset state. 
+                       // Note: Only reset when all uart buffers have been 
transmitted, 
+                       // otherwise the timeout would start from the beginning 
and the 
+                       // loop phase shifts (aka "you're in the deep"). 
+                       uart1_num_rx_bytes = 0; 
+                       uart2_num_rx_bytes = 0; 
+                       uart3_num_rx_bytes = 0; 
+                       timeout_uart1 = 0; 
+                       timeout_uart2 = 0; 
+                       timeout_uart3 = 0; 
+                       uart1_sent = 0; 
+                       uart2_sent = 0; 
+                       uart3_sent = 0; 
+    }
+  } 
+}




reply via email to

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