--- /dev/null
+// $Id$
+
+/* tab:4
+ * "Copyright (c) 2000-2003 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2003 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/**
+ * The TinyOS 2.x base station that forwards packets between the UART
+ * and radio.It replaces the GenericBase of TinyOS 1.0 and the
+ * TOSBase of TinyOS 1.1.
+ *
+ * <p>On the serial link, BaseStation sends and receives simple active
+ * messages (not particular radio packets): on the radio link, it
+ * sends radio active messages, whose format depends on the network
+ * stack being used. BaseStation will copy its compiled-in group ID to
+ * messages moving from the serial link to the radio, and will filter
+ * out incoming radio messages that do not contain that group ID.</p>
+ *
+ * <p>BaseStation includes queues in both directions, with a guarantee
+ * that once a message enters a queue, it will eventually leave on the
+ * other interface. The queues allow the BaseStation to handle load
+ * spikes.</p>
+ *
+ * <p>BaseStation acknowledges a message arriving over the serial link
+ * only if that message was successfully enqueued for delivery to the
+ * radio link.</p>
+ *
+ * <p>The LEDS are programmed to toggle as follows:</p>
+ * <ul>
+ * <li><b>RED Toggle:</b>: Message bridged from serial to radio</li>
+ * <li><b>GREEN Toggle:</b> Message bridged from radio to serial</li>
+ * <li><b>YELLOW/BLUE Toggle:</b> Dropped message due to queue overflow in either direction</li>
+ * </ul>
+ *
+ * @author Phil Buonadonna
+ * @author Gilman Tolle
+ * @author David Gay
+ * @author Philip Levis
+ * @date August 10 2005
+ */
+
+configuration BaseStationC {
+}
+implementation {
+ components MainC, BaseStationP, LedsC;
+ components ActiveMessageC as Radio, SerialActiveMessageC as Serial;
+
+ MainC.Boot <- BaseStationP;
+
+ BaseStationP.RadioControl -> Radio;
+ BaseStationP.SerialControl -> Serial;
+
+ BaseStationP.UartSend -> Serial;
+ BaseStationP.UartReceive -> Serial.Receive;
+ BaseStationP.UartPacket -> Serial;
+ BaseStationP.UartAMPacket -> Serial;
+
+ BaseStationP.RadioSend -> Radio;
+ BaseStationP.RadioReceive -> Radio.Receive;
+ BaseStationP.RadioSnoop -> Radio.Snoop;
+ BaseStationP.RadioPacket -> Radio;
+ BaseStationP.RadioAMPacket -> Radio;
+
+ BaseStationP.Leds -> LedsC;
+}
--- /dev/null
+// $Id$
+
+/* tab:4
+ * "Copyright (c) 2000-2005 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice, the following
+ * two paragraphs and the author appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
+ *
+ * Copyright (c) 2002-2005 Intel Corporation
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached INTEL-LICENSE
+ * file. If you do not find these files, copies can be found by writing to
+ * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
+ * 94704. Attention: Intel License Inquiry.
+ */
+
+/*
+ * @author Phil Buonadonna
+ * @author Gilman Tolle
+ * @author David Gay
+ * Revision: $Id$
+ */
+
+/*
+ * BaseStationP bridges packets between a serial channel and the radio.
+ * Messages moving from serial to radio will be tagged with the group
+ * ID compiled into the TOSBase, and messages moving from radio to
+ * serial will be filtered by that same group id.
+ */
+
+#include "AM.h"
+#include "Serial.h"
+
+module BaseStationP @safe() {
+ uses {
+ interface Boot;
+ interface SplitControl as SerialControl;
+ interface SplitControl as RadioControl;
+
+ interface AMSend as UartSend[am_id_t id];
+ interface Receive as UartReceive[am_id_t id];
+ interface Packet as UartPacket;
+ interface AMPacket as UartAMPacket;
+
+ interface AMSend as RadioSend[am_id_t id];
+ interface Receive as RadioReceive[am_id_t id];
+ interface Receive as RadioSnoop[am_id_t id];
+ interface Packet as RadioPacket;
+ interface AMPacket as RadioAMPacket;
+
+ interface Leds;
+ }
+}
+
+implementation
+{
+ enum {
+ UART_QUEUE_LEN = 12,
+ RADIO_QUEUE_LEN = 12,
+ };
+
+ message_t uartQueueBufs[UART_QUEUE_LEN];
+ message_t * ONE_NOK uartQueue[UART_QUEUE_LEN];
+ uint8_t uartIn, uartOut;
+ bool uartBusy, uartFull;
+
+ message_t radioQueueBufs[RADIO_QUEUE_LEN];
+ message_t * ONE_NOK radioQueue[RADIO_QUEUE_LEN];
+ uint8_t radioIn, radioOut;
+ bool radioBusy, radioFull;
+
+ task void uartSendTask();
+ task void radioSendTask();
+
+ void dropBlink() {
+ call Leds.led2Toggle();
+ }
+
+ void failBlink() {
+ call Leds.led2Toggle();
+ }
+
+ event void Boot.booted() {
+ uint8_t i;
+
+ for (i = 0; i < UART_QUEUE_LEN; i++)
+ uartQueue[i] = &uartQueueBufs[i];
+ uartIn = uartOut = 0;
+ uartBusy = FALSE;
+ uartFull = TRUE;
+
+ for (i = 0; i < RADIO_QUEUE_LEN; i++)
+ radioQueue[i] = &radioQueueBufs[i];
+ radioIn = radioOut = 0;
+ radioBusy = FALSE;
+ radioFull = TRUE;
+
+ call RadioControl.start();
+ call SerialControl.start();
+ }
+
+ event void RadioControl.startDone(error_t error) {
+ if (error == SUCCESS) {
+ radioFull = FALSE;
+ }
+ }
+
+ event void SerialControl.startDone(error_t error) {
+ if (error == SUCCESS) {
+ uartFull = FALSE;
+ }
+ }
+
+ event void SerialControl.stopDone(error_t error) {}
+ event void RadioControl.stopDone(error_t error) {}
+
+ uint8_t count = 0;
+
+ message_t* ONE receive(message_t* ONE msg, void* payload, uint8_t len);
+
+ event message_t *RadioSnoop.receive[am_id_t id](message_t *msg,
+ void *payload,
+ uint8_t len) {
+ return receive(msg, payload, len);
+ }
+
+ event message_t *RadioReceive.receive[am_id_t id](message_t *msg,
+ void *payload,
+ uint8_t len) {
+ return receive(msg, payload, len);
+ }
+
+ message_t* receive(message_t *msg, void *payload, uint8_t len) {
+ message_t *ret = msg;
+
+ atomic {
+ if (!uartFull)
+ {
+ ret = uartQueue[uartIn];
+ uartQueue[uartIn] = msg;
+
+ uartIn = (uartIn + 1) % UART_QUEUE_LEN;
+
+ if (uartIn == uartOut)
+ uartFull = TRUE;
+
+ if (!uartBusy)
+ {
+ post uartSendTask();
+ uartBusy = TRUE;
+ }
+ }
+ else
+ dropBlink();
+ }
+
+ return ret;
+ }
+
+ uint8_t tmpLen;
+
+ task void uartSendTask() {
+ uint8_t len;
+ am_id_t id;
+ am_addr_t addr, src;
+ message_t* msg;
+ atomic
+ if (uartIn == uartOut && !uartFull)
+ {
+ uartBusy = FALSE;
+ return;
+ }
+
+ msg = uartQueue[uartOut];
+ tmpLen = len = call RadioPacket.payloadLength(msg);
+ id = call RadioAMPacket.type(msg);
+ addr = call RadioAMPacket.destination(msg);
+ src = call RadioAMPacket.source(msg);
+ call UartPacket.clear(msg);
+ call UartAMPacket.setSource(msg, src);
+
+ if (call UartSend.send[id](addr, uartQueue[uartOut], len) == SUCCESS)
+ call Leds.led1Toggle();
+ else
+ {
+ failBlink();
+ post uartSendTask();
+ }
+ }
+
+ event void UartSend.sendDone[am_id_t id](message_t* msg, error_t error) {
+ if (error != SUCCESS)
+ failBlink();
+ else
+ atomic
+ if (msg == uartQueue[uartOut])
+ {
+ if (++uartOut >= UART_QUEUE_LEN)
+ uartOut = 0;
+ if (uartFull)
+ uartFull = FALSE;
+ }
+ post uartSendTask();
+ }
+
+ event message_t *UartReceive.receive[am_id_t id](message_t *msg,
+ void *payload,
+ uint8_t len) {
+ message_t *ret = msg;
+ bool reflectToken = FALSE;
+
+ atomic
+ if (!radioFull)
+ {
+ reflectToken = TRUE;
+ ret = radioQueue[radioIn];
+ radioQueue[radioIn] = msg;
+ if (++radioIn >= RADIO_QUEUE_LEN)
+ radioIn = 0;
+ if (radioIn == radioOut)
+ radioFull = TRUE;
+
+ if (!radioBusy)
+ {
+ post radioSendTask();
+ radioBusy = TRUE;
+ }
+ }
+ else
+ dropBlink();
+
+ if (reflectToken) {
+ //call UartTokenReceive.ReflectToken(Token);
+ }
+
+ return ret;
+ }
+
+ task void radioSendTask() {
+ uint8_t len;
+ am_id_t id;
+ am_addr_t addr,source;
+ message_t* msg;
+
+ atomic
+ if (radioIn == radioOut && !radioFull)
+ {
+ radioBusy = FALSE;
+ return;
+ }
+
+ msg = radioQueue[radioOut];
+ len = call UartPacket.payloadLength(msg);
+ addr = call UartAMPacket.destination(msg);
+ source = call UartAMPacket.source(msg);
+ id = call UartAMPacket.type(msg);
+
+ call RadioPacket.clear(msg);
+ call RadioAMPacket.setSource(msg, source);
+
+ if (call RadioSend.send[id](addr, msg, len) == SUCCESS)
+ call Leds.led0Toggle();
+ else
+ {
+ failBlink();
+ post radioSendTask();
+ }
+ }
+
+ event void RadioSend.sendDone[am_id_t id](message_t* msg, error_t error) {
+ if (error != SUCCESS)
+ failBlink();
+ else
+ atomic
+ if (msg == radioQueue[radioOut])
+ {
+ if (++radioOut >= RADIO_QUEUE_LEN)
+ radioOut = 0;
+ if (radioFull)
+ radioFull = FALSE;
+ }
+
+ post radioSendTask();
+ }
+}