]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - apps/tosthreads/capps/BaseStation/BaseStation.c
initial checkin of tosthreads related apps
[tinyos-2.x.git] / apps / tosthreads / capps / BaseStation / BaseStation.c
diff --git a/apps/tosthreads/capps/BaseStation/BaseStation.c b/apps/tosthreads/capps/BaseStation/BaseStation.c
new file mode 100644 (file)
index 0000000..6aa4953
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2008 Stanford University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the
+ *   distribution.
+ * - Neither the name of the Stanford University nor the names of
+ *   its contributors may be used to endorse or promote products derived
+ *   from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL STANFORD
+ * UNIVERSITY OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Base station implementation using tosthreads
+ *
+ * @author Kevin Klues <klueska@cs.stanford.edu>
+ */
+
+//#include "stack.h"
+#include "tosthread.h"
+#include "tosthread_amradio.h"
+#include "tosthread_amserial.h"
+#include "tosthread_leds.h"
+#include "tosthread_threadsync.h"
+
+#define MSG_QUEUE_SIZE  3
+
+//Parameters associated with each of the two base station paths
+// radio -> serial
+// serial -> radio
+typedef struct bs_params {
+  tosthread_t receive_handle;
+  tosthread_t snoop_handle;
+  tosthread_t send_handle;
+  mutex_t     mutex;
+  condvar_t   condvar;
+  message_t   shared_msgs[MSG_QUEUE_SIZE];
+  uint8_t     shared_msg_queue_size;
+  uint8_t     shared_msg_queue_index;
+} bs_params_t;
+
+//Declare parameters associated with radio RX thread
+bs_params_t radioRx_params;
+void radioReceive_thread(void* arg);
+void radioSnoop_thread(void* arg);
+void serialSend_thread(void* arg);
+
+//Declare parameters associated with serial RX thread
+bs_params_t serialRx_params;
+void serialReceive_thread(void* arg);
+void radioSend_thread(void* arg);
+
+/********* Initialize base station parameters ********/
+void bs_params_init(bs_params_t* p) {
+  mutex_init( &(p->mutex) );
+  condvar_init( &(p->condvar) );
+  p->shared_msg_queue_size = 0;
+  p->shared_msg_queue_index = 0;
+}
+
+/*********** Main function thread ************/
+void tosthread_main(void* arg) {
+  bs_params_init( &radioRx_params );
+  bs_params_init( &serialRx_params );
+
+  amRadioStart();
+  amSerialStart();
+  tosthread_create(&(radioRx_params.receive_handle), radioReceive_thread, NULL, 200);
+  tosthread_create(&(radioRx_params.snoop_handle), radioSnoop_thread, NULL, 200);
+  tosthread_create(&(radioRx_params.send_handle), serialSend_thread, NULL, 200);
+  tosthread_create(&(serialRx_params.receive_handle), serialReceive_thread, NULL, 200);
+  tosthread_create(&(serialRx_params.send_handle), radioSend_thread, NULL, 200);
+}
+
+/******************** Enqueue and dequeue Messages ****************/
+error_t enqueueMsg(bs_params_t* p, message_t* m) {
+  if(p->shared_msg_queue_size < MSG_QUEUE_SIZE) {
+    (p->shared_msgs)[p->shared_msg_queue_index] = *m;
+    (p->shared_msg_queue_index) = (p->shared_msg_queue_index + 1) % MSG_QUEUE_SIZE;
+    (p->shared_msg_queue_size)++;
+    return SUCCESS;
+  }
+  return FAIL;
+}
+
+message_t* dequeueMsg(bs_params_t* p) {
+  if(p->shared_msg_queue_size > 0) {
+    message_t* m;
+    m = &((p->shared_msgs)[(p->shared_msg_queue_index + (MSG_QUEUE_SIZE - p->shared_msg_queue_size)) % MSG_QUEUE_SIZE]);
+    (p->shared_msg_queue_size)--;
+    return m;
+  }
+  return NULL;
+}
+
+/******************** Send Serial vs. Radio Messages ****************/
+error_t sendSerialMsg(message_t* msg) {
+  am_id_t   id     = amRadioGetType(msg);
+  am_addr_t source = amRadioGetSource(msg);
+  am_addr_t dest   = amRadioGetDestination(msg);
+  uint8_t   len    = radioGetPayloadLength(msg);
+  serialClear(msg);
+  amSerialSetSource(msg, source);
+      
+  return amSerialSend(dest, msg, len, id);
+}
+
+error_t sendRadioMsg(message_t* msg) {
+  am_id_t   id     = amSerialGetType(msg);
+  am_addr_t source = amSerialGetSource(msg);
+  am_addr_t dest   = amSerialGetDestination(msg);
+  uint8_t   len    = serialGetPayloadLength(msg);
+  radioClear(msg);
+  amRadioSetSource(msg, source);
+      
+  return amRadioSend(dest, msg, len, id);
+}
+
+
+/***********************************************************/
+/** Generic implementations of send/receive functionality **/ 
+/***********************************************************/
+void bs_receive(error_t (*recv_func)(message_t*, uint32_t, am_id_t), bs_params_t* p) {
+  message_t m;
+  
+  for(;;) {
+    if( (*(recv_func))(&m, 0, AM_RECEIVE_FROM_ANY) == SUCCESS ) {
+      led0Toggle();
+
+      mutex_lock( &(p->mutex) );
+        while( enqueueMsg(p, &m) == FAIL )
+          condvar_wait( &(p->condvar), &(p->mutex) );
+      mutex_unlock( &(p->mutex) );
+      condvar_signalAll( &(p->condvar) );
+    }
+    else led2Toggle();
+  }
+}
+
+void bs_send(void* send_func, bs_params_t* p) {
+  message_t m;
+  message_t* m_ptr;
+  
+  for(;;) {
+    mutex_lock( &(p->mutex) );
+      while( (m_ptr = dequeueMsg(p)) == NULL )
+        condvar_wait( &(p->condvar), &(p->mutex) );
+      m = *m_ptr;
+    mutex_unlock( &(p->mutex) );    
+    condvar_signalAll( &(p->condvar) );
+    
+    if(send_func == amSerialSend)
+      sendSerialMsg(&m);
+    else
+      sendRadioMsg(&m);
+    led1Toggle();
+  }  
+}
+
+/******************** Actual thread implementations ******************/
+void radioReceive_thread(void* arg) {
+  bs_receive(amRadioReceive, &radioRx_params);
+}
+void radioSnoop_thread(void* arg) {
+  bs_receive(amRadioSnoop, &radioRx_params);
+}
+void serialSend_thread(void* arg) {
+  bs_send(amSerialSend, &radioRx_params);
+}
+void serialReceive_thread(void* arg) {
+  bs_receive(amSerialReceive, &serialRx_params);
+}
+void radioSend_thread(void* arg) {
+  bs_send(amRadioSend, &serialRx_params);
+}