⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basestationp.nc

📁 tinyos-2.x.rar
💻 NC
字号:
/*
 * "Copyright (c) 2008 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."
 *
 */
// $Id: BaseStationP.nc,v 1.5 2009/09/19 21:13:26 sdhsdh Exp $

/*									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.nc,v 1.5 2009/09/19 21:13:26 sdhsdh Exp $
 */
  
/* 
 * 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.
 */

#ifndef SIM
#include "CC2420.h"
#endif
#include "AM.h"
#include "Serial.h"
#include "devconf.h"
#include "lib6lowpan.h"

module BaseStationP {
  uses {
    interface Boot;
    interface SplitControl as SerialControl;
    interface SplitControl as RadioControl;

    interface Send as UartSend;
    interface Ieee154Send as RadioSend;

    interface Receive as UartReceive;
    interface Receive as RadioReceive;
    interface Packet as RadioPacket;

    interface Send as ConfigureSend;
    interface Receive as ConfigureReceive;
    interface Timer<TMilli> as ConfigureTimer;
    interface IPAddress;


    interface Ieee154Packet as RadioIeeePacket;

    interface PacketLink;
    interface LowPowerListening;
    interface CC2420Config;

    interface Leds;

    interface Reset;
  }
}

implementation
{
  enum {
    UART_QUEUE_LEN = 10,
    RADIO_QUEUE_LEN = 10,
  };

  uint16_t radioRetries = BLIP_L2_RETRIES;
  uint16_t radioDelay   = BLIP_L2_DELAY;

  uint16_t serial_read;
  uint16_t radio_read;
  uint16_t serial_fail;
  uint16_t radio_fail;

  bool echo_busy;
  message_t echo_buf;
  config_reply_t *reply;

  message_t  uartQueueBufs[UART_QUEUE_LEN];
  message_t  *uartQueue[UART_QUEUE_LEN];
  uint8_t    uartIn, uartOut;
  bool       uartBusy, uartFull;

  message_t  radioQueueBufs[RADIO_QUEUE_LEN];
  message_t  *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();
  }

#ifndef SIM
#define CHECK_NODE_ID if (0) return
#else
#define CHECK_NODE_ID if (TOS_NODE_ID != BASESTATION_ID) return
#endif
  task void configureReply() {
    if (echo_busy) return;

    reply->addr = call IPAddress.getShortAddr();
    reply->serial_read = serial_read;
    reply->radio_read = radio_read;
    reply->serial_fail = serial_fail;
    reply->radio_fail = radio_fail;

    echo_busy = TRUE;
    // delay sending the reply for a bit
    // the pc seems to usually drop the packet if we don't do this; 
    call ConfigureTimer.startOneShot(100);
  }

  event void Boot.booted() {
    uint8_t i;

    CHECK_NODE_ID;

    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;

    echo_busy = FALSE;
    serial_read = 0;
    radio_read = 0;
    serial_fail = 0;
    radio_fail = 0;

    call RadioControl.start();
    call SerialControl.start();

    reply = (config_reply_t *)(&(echo_buf.data));
  }

  event void RadioControl.startDone(error_t error) {
    CHECK_NODE_ID;
    if (error == SUCCESS) {
      radioFull = FALSE;
#ifdef LPL_SLEEP_INTERVAL
      // SDH : can actually leave the base on full time in most cases.
      // call LowPowerListening.setLocalSleepInterval(LPL_SLEEP_INTERVAL);
#endif
    }
  }

  event void SerialControl.startDone(error_t error) {
    CHECK_NODE_ID;
    if (error == SUCCESS) {
      uartFull = FALSE;
    }
    reply->error = CONFIG_ERROR_BOOTED;
    post configureReply();
  }

  event void SerialControl.stopDone(error_t error) {}
  event void RadioControl.stopDone(error_t error) {}

  uint8_t count = 0;

  message_t* receive(message_t* msg, void* payload, uint8_t len);
  
  event message_t *RadioReceive.receive(message_t *msg,
                                           void *payload,
                                           uint8_t len) {
    CHECK_NODE_ID NULL;
    dbg("base", "radio message received (%i)\n", len);
    return receive(msg, payload, len);
  }

  message_t* receive(message_t *msg, void *payload, uint8_t len) {
    message_t *ret = msg;
    CHECK_NODE_ID NULL;

    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;
  }

  task void uartSendTask() {
    uint8_t len;
    message_t* msg;
    atomic
      if (uartIn == uartOut && !uartFull)
	{
	  uartBusy = FALSE;
	  return;
	}

    msg = uartQueue[uartOut];

    // Since we're forwarding fully formed radio packets, we can use
    // these headers.
    len = call RadioPacket.payloadLength(msg);

    if (call UartSend.send(uartQueue[uartOut], len) == SUCCESS) {
      call Leds.led1Toggle();
    }    else
      {
	failBlink();
	post uartSendTask();
      }
  }

  event void UartSend.sendDone(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(message_t *msg,
                                       void *payload,
                                       uint8_t len) {
    message_t *ret = msg;
    bool reflectToken = FALSE;
    CHECK_NODE_ID msg;
    dbg("base", "uartreceive len %i of 0x%x\n", len, call SerialAMPacket.destination(msg));
#if defined(BLIP_WATCHDOG) && (defined(PLATFORM_TELOS) || defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC))
    WDTCTL = WDT_ARST_1000;
#endif
    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
        dbg("base", "no enqueue\n");
// 	dropBlink();

    if (reflectToken) {
      //call UartTokenReceive.ReflectToken(Token);
    }
    
    return ret;
  }

  task void radioSendTask() {
    uint8_t len;
    ieee154_saddr_t addr;
    message_t* msg;
    
    dbg ("base", "radioSendTask()\n");
    atomic
      if (radioIn == radioOut && !radioFull)
	{
	  radioBusy = FALSE;
	  return;
	}

    msg = radioQueue[radioOut];
    len = call RadioPacket.payloadLength(msg);
    addr = call RadioIeeePacket.destination(msg);

    if (addr != 0xFFFF) {
      call PacketLink.setRetries(msg, radioRetries);
      call PacketLink.setRetryDelay(msg, radioDelay);
    } else {
      call PacketLink.setRetries(msg, 0);
    }
#ifdef LPL_SLEEP_INTERVAL
    call LowPowerListening.setRemoteWakeupInterval(msg, LPL_SLEEP_INTERVAL);
#endif
    dbg("base", "radio send to: 0x%x len: %i\n", addr, len);
    if (call RadioSend.send(addr, msg, len) == SUCCESS)
      call Leds.led0Toggle();
    else
      {
	failBlink();
	post radioSendTask();
      }
  }

  event void RadioSend.sendDone(message_t* msg, error_t error) {
    CHECK_NODE_ID;
    dbg("base", "sendDone()\n");
    
    //if (!call PacketLink.wasDelivered(msg))
    // failBlink();
    if (error != SUCCESS)
      failBlink();
    else
      atomic
	if (msg == radioQueue[radioOut])
	  {
	    if (++radioOut >= RADIO_QUEUE_LEN)
	      radioOut = 0;
	    if (radioFull)
	      radioFull = FALSE;
	  }
    
    post radioSendTask();
  }

#ifndef SIM
  event message_t *ConfigureReceive.receive(message_t *msg,
                                            void *payload,
                                            uint8_t len) {
    config_cmd_t *cmd;
    uint8_t error = CONFIG_ERROR_OK;
#if defined(BLIP_WATCHDOG) && (defined(PLATFORM_TELOS) || defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC))
    WDTCTL = WDT_ARST_1000;
#endif

    if (len != sizeof(config_cmd_t) || msg == NULL) return msg;
    // don't parse the message if we can't reply

    cmd = (config_cmd_t *)&msg->data;

    switch (cmd->cmd) {
    case CONFIG_ECHO:
      break;
    case CONFIG_SET_PARM:
      call CC2420Config.setChannel(cmd->rf.channel);
      // IPAddress calls sync() for you, I think, so we'll put it second 
      call IPAddress.setShortAddr(cmd->rf.addr);
      call CC2420Config.sync();
      radioRetries = cmd->retx.retries;
      radioDelay   = cmd->retx.delay;
      break;
    case CONFIG_REBOOT:
      call Reset.reset();
      break;
    case CONFIG_KEEPALIVE:
      return msg;
    }
    if (!echo_busy) {
      reply->error = error;
      post configureReply();
    }
    return msg;
  }


  event void CC2420Config.syncDone(error_t error) {

  }

  event void ConfigureSend.sendDone(message_t *msg, error_t error) {
    echo_busy = FALSE;
  }

  event void ConfigureTimer.fired() {
    call Leds.led2Toggle();
    if (call ConfigureSend.send(&echo_buf, sizeof(config_reply_t)) != SUCCESS)
      echo_busy = FALSE;
  }
#endif
}  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -