[Tinyos-contrib-commits] CVS: tinyos-1.x/contrib/GGB/tos/lib/MintRoute FixRoute.nc, NONE, 1.1 MultiHop.h, NONE, 1.1 MultiHopEngineM.nc, NONE, 1.1 MultiHopWMEWMA.nc, NONE, 1.1 README, NONE, 1.1 WMEWMAMultiHopRouter.nc, NONE, 1.1

Sukun Kim binetude at users.sourceforge.net
Tue Jun 20 15:05:58 PDT 2006


Update of /cvsroot/tinyos/tinyos-1.x/contrib/GGB/tos/lib/MintRoute
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv15568/MintRoute

Added Files:
	FixRoute.nc MultiHop.h MultiHopEngineM.nc MultiHopWMEWMA.nc 
	README WMEWMAMultiHopRouter.nc 
Log Message:


--- NEW FILE: FixRoute.nc ---
interface FixRoute {
  command result_t fix();
  command result_t release();
  command uint8_t getFixedRoute();

  command uint16_t getParent();
  command uint8_t getDepth();
}


--- NEW FILE: MultiHop.h ---
// $Id: MultiHop.h,v 1.1 2006/06/20 22:05:56 binetude Exp $

/*									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.
 */

/*
 *
 * Authors:		Philip Buonadonna, Alec Woo, Terence Tong, Crossbow
 * Date last modified:  2/20/03
 *
 */


#ifndef _TOS_MULTIHOP_H
#define _TOS_MULTIHOP_H

#include "AM.h"
enum {
  AM_MULTIHOPMSG = 250,
  AM_DEBUGPACKET = 3 
};

/* Fields of neighbor table */
typedef struct TOS_MHopNeighbor {
  uint16_t addr;                     // state provided by nbr
  uint16_t recv_count;               // since last goodness update
  uint16_t fail_count;               // since last goodness, adjusted by TOs
  int16_t last_seqno;
  uint8_t goodness;
  uint8_t hopcount;
  uint8_t timeouts;		     // since last recv
} TOS_MHopNeighbor;
  
typedef struct MultihopMsg {
  uint16_t sourceaddr;
  uint16_t originaddr;
  int16_t seqno;
  uint8_t hopcount;
  uint8_t data[(TOSH_DATA_LENGTH - 7)]; 
} __attribute__ ((packed)) TOS_MHopMsg;

typedef struct DBGEstEntry {
  uint16_t id;
  uint8_t hopcount;
  uint8_t sendEst;
} __attribute__ ((packed)) DBGEstEntry;


typedef struct DebugPacket {
  uint8_t estEntries;
  DBGEstEntry estList[5];
} __attribute__ ((packed)) DebugPacket;


#endif /* _TOS_MULTIHOP_H */

--- NEW FILE: MultiHopEngineM.nc ---
// $Id: MultiHopEngineM.nc,v 1.1 2006/06/20 22:05:56 binetude Exp $

/*									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.
 */

/* 
 * A simple module that handles multihop packet movement.  It accepts 
 * messages from both applications and the network and does the necessary
 * interception and forwarding.
 * It interfaces to an algorithmic componenet via RouteSelect. It also acts
 * as a front end for RouteControl
 */

includes AM;
includes MultiHop;

#ifndef MHOP_QUEUE_SIZE
#define MHOP_QUEUE_SIZE	16
#endif

module MultiHopEngineM {
  provides {
    interface StdControl;
    interface Receive[uint8_t id];
    interface Send[uint8_t id];
    interface Intercept[uint8_t id];
    interface Intercept as Snoop[uint8_t id];
    interface RouteControl;
  }
  uses {
    interface ReceiveMsg[uint8_t id];
    interface SendMsg[uint8_t id];
    interface RouteControl as RouteSelectCntl;
    interface RouteSelect;
    interface StdControl as SubControl;
    interface CommControl;
    interface StdControl as CommStdControl;
  }
}

implementation {

  enum {
    FWD_QUEUE_SIZE = MHOP_QUEUE_SIZE, // Forwarding Queue
    EMPTY = 0xff
  };


  /* Routing status of local node */


  /* Internal storage and scheduling state */
  TOS_Msg FwdBuffers[FWD_QUEUE_SIZE];
  TOS_Msg *FwdBufList[FWD_QUEUE_SIZE];

  uint8_t iFwdBufHead, iFwdBufTail;

  int timer_rate,timer_ticks;
  
  /***********************************************************************
   * Initialization 
   ***********************************************************************/


  static void initialize() {
    int n;

    for (n=0; n < FWD_QUEUE_SIZE; n++) {
      FwdBufList[n] = &FwdBuffers[n];
    } 

    iFwdBufHead = iFwdBufTail = 0;
  }

  command result_t StdControl.init() {
    initialize();
    call CommStdControl.init();
    return call SubControl.init();
  }

  command result_t StdControl.start() {
    call CommStdControl.start();
    call SubControl.start();
    return call CommControl.setPromiscuous(TRUE);
  }

  command result_t StdControl.stop() {
    call SubControl.stop();
    // XXX message doesn't get received if we stop then start radio
    return call CommStdControl.stop();
  }


  /***********************************************************************
   * Commands and events
   ***********************************************************************/

  command result_t Send.send[uint8_t id](TOS_MsgPtr pMsg, uint16_t PayloadLen) {

    uint16_t usMHLength = offsetof(TOS_MHopMsg,data) + PayloadLen;

    if (usMHLength > TOSH_DATA_LENGTH) {
      return FAIL;
    }

    //dbg(DBG_ROUTE,"MHop: send\n");

    call RouteSelect.initializeFields(pMsg,id);

    if (call RouteSelect.selectRoute(pMsg,id) != SUCCESS) {
      return FAIL;
    }

    //dbg(DBG_ROUTE,"MHop: out pkt 0x%x\n",((TOS_MHopMsg *)pMsg->data)->seqno);
    
    if (call SendMsg.send[id](pMsg->addr, usMHLength, pMsg) != SUCCESS) {
      return FAIL;
    }

    return SUCCESS;
    
  } 

  command void *Send.getBuffer[uint8_t id](TOS_MsgPtr pMsg, uint16_t* length) {
    
    TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)pMsg->data;
    
    *length = TOSH_DATA_LENGTH - offsetof(TOS_MHopMsg,data);

    return (&pMHMsg->data[0]);

  }

  
  static TOS_MsgPtr mForward(TOS_MsgPtr pMsg, uint8_t id) {
    TOS_MsgPtr	pNewBuf = pMsg;
    
    if (((iFwdBufHead + 1) % FWD_QUEUE_SIZE) == iFwdBufTail) 
      return pNewBuf;
    
    if ((call RouteSelect.selectRoute(pMsg,id)) != SUCCESS) 
      return pNewBuf;
 
    // Failures at the send level do not cause the seq. number space to be 
    // rolled back properly.  This is somewhat broken.
    if (call SendMsg.send[id](pMsg->addr,pMsg->length,pMsg) == SUCCESS) {
      pNewBuf = FwdBufList[iFwdBufHead];
      FwdBufList[iFwdBufHead] = pMsg;
      iFwdBufHead++; iFwdBufHead %= FWD_QUEUE_SIZE;
    }
    
    return pNewBuf;
    
  }

  event TOS_MsgPtr ReceiveMsg.receive[uint8_t id](TOS_MsgPtr pMsg) {
    TOS_MHopMsg		*pMHMsg = (TOS_MHopMsg *)pMsg->data;
    uint16_t		PayloadLen = pMsg->length - offsetof(TOS_MHopMsg,data);

#if 0
    dbg(DBG_ROUTE, "MHop: Msg Rcvd, src 0x%02x, org 0x%02x, parent 0x%02x\n", 
        pMHMsg->sourceaddr, pMHMsg->originaddr, 0 /*pMHMsg->parentaddr*/);
#endif

    // Ordinary message requiring forwarding
    if (pMsg->addr == TOS_LOCAL_ADDRESS) { // Addressed to local node
      if ((signal Intercept.intercept[id](pMsg,&pMHMsg->data[0],PayloadLen)) == SUCCESS) {
        pMsg = mForward(pMsg,id);
      }
    }
    else {
      // Snoop the packet for permiscuous applications
      signal Snoop.intercept[id](pMsg,&pMHMsg->data[0],PayloadLen);
    }

    return pMsg;
  }

  event result_t SendMsg.sendDone[uint8_t id](TOS_MsgPtr pMsg, result_t success) {
    //dbg(DBG_ROUTE, "MHop: senddone 0x%x 0x%x\n", pMsg, success);  
    if (pMsg == FwdBufList[iFwdBufTail]) { // Msg was from forwarding queue
      iFwdBufTail++; iFwdBufTail %= FWD_QUEUE_SIZE;
    } else {
      signal Send.sendDone[id](pMsg, success);
    } 
    return SUCCESS;
  }

  command uint16_t RouteControl.getParent() {
    return call RouteSelectCntl.getParent();
  }

  command uint8_t RouteControl.getQuality() {
    return call RouteSelectCntl.getQuality();
  }

  command uint8_t RouteControl.getDepth() {
    return call RouteSelectCntl.getDepth();
  }

  command uint8_t RouteControl.getOccupancy() {
    uint16_t uiOutstanding = (uint16_t)iFwdBufTail - (uint16_t)iFwdBufHead;
    uiOutstanding %= FWD_QUEUE_SIZE;
    return (uint8_t)uiOutstanding;
  }

  command uint16_t RouteControl.getSender(TOS_MsgPtr msg) {
    TOS_MHopMsg	 *pMHMsg = (TOS_MHopMsg *)msg->data;
    return pMHMsg->sourceaddr;
  }

  command result_t RouteControl.setUpdateInterval(uint16_t Interval) {
    return call RouteSelectCntl.setUpdateInterval(Interval);
  }

  command result_t RouteControl.manualUpdate() {
    return call RouteSelectCntl.manualUpdate();
  }

  default event result_t Send.sendDone[uint8_t id](TOS_MsgPtr pMsg, result_t success) {
    return SUCCESS;
  }

  default event result_t Intercept.intercept[uint8_t id](TOS_MsgPtr pMsg, void* payload, 
							 uint16_t payloadLen) {
    return SUCCESS;
  }

  default event result_t Snoop.intercept[uint8_t id](TOS_MsgPtr pMsg, void* payload, 
                                                     uint16_t payloadLen) {
    return SUCCESS;
  }

}

--- NEW FILE: MultiHopWMEWMA.nc ---
// $Id: MultiHopWMEWMA.nc,v 1.1 2006/06/20 22:05:56 binetude Exp $

/*									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.
 */

/*
 *
 * Authors:		Philip Buonadonna, Alec Woo, Terence Tong, Crossbow
 * Date last modified:  2/20/03
 *
 */


includes AM;
includes MultiHop;


//#define MULTI_HOP_DEBUG 1

module MultiHopWMEWMA {

  provides {
    interface StdControl;
    interface RouteSelect;
    interface RouteControl;
    interface FixRoute;
  }

  uses {
    interface Leds;
    interface Timer;
    interface Timer as ATimer;
    interface ReceiveMsg;
    interface Intercept as Snoop[uint8_t id];
    interface SendMsg;
    interface Send as DebugSendMsg;
#ifdef USE_WATCHDOG
	interface StdControl as PoochHandler;
	interface WDT;
#endif
  }
}

implementation {

  enum {
    NBRFLAG_VALID    = 0x01,
    NBRFLAG_NEW      = 0x02,
    NBRFLAG_EST_INIT = 0x04
  };

  enum {
    BASE_STATION_ADDRESS        = 0,
    ROUTE_TABLE_SIZE            = 16,
    ESTIMATE_TO_ROUTE_RATIO     = 10,
    ACCEPTABLE_MISSED           = -20,
    DATA_TO_ROUTE_RATIO         = 1,
    DATA_FREQ                   = 8192,
    SWITCH_THRESHOLD     	= 384,
    MAX_ALLOWABLE_LINK_COST     = 256*6,
    LIVELINESS              	= 5,
    MAX_DESCENDANT_LIVE		= 5

  };

  enum {
    ROUTE_INVALID    = 0xff
  };

  struct SortEntry {
    uint16_t id;
    uint8_t  receiveEst;
  };

  struct SortDbgEntry {
    uint16_t id;
    uint8_t  sendEst;
    uint8_t  hopcount; 
  };

  typedef struct RPEstEntry {
    uint16_t id;
    uint8_t receiveEst;
  } __attribute__ ((packed)) RPEstEntry;

  typedef struct RoutePacket {
    uint16_t parent;
    uint16_t cost;
    uint8_t estEntries;
    RPEstEntry estList[1];
  } __attribute__ ((packed)) RoutePacket;

  typedef struct TableEntry {
    uint16_t id;  // Node Address
    uint16_t parent;
    uint16_t cost;
    uint8_t childLiveliness;
    uint16_t missed;
    uint16_t received;
    int16_t lastSeqno;
    uint8_t flags;
    uint8_t liveliness;
    uint8_t hop;
    uint8_t receiveEst;
    uint8_t sendEst;
  } TableEntry;

  TOS_Msg debugMsg; 
  TOS_Msg routeMsg; 
  bool gfSendRouteBusy;
  bool gSelfTimer;

  TableEntry BaseStation;
  TableEntry NeighborTbl[ROUTE_TABLE_SIZE];
  TableEntry *gpCurrentParent;
  uint8_t gbCurrentHopCount;
  uint16_t gbCurrentCost;
  int16_t gCurrentSeqNo;
  uint16_t gwEstTicks;
  uint32_t gUpdateInterval;

  bool fixedRoute;
  uint16_t fixedParent;
  uint8_t fixedDepth;
  

  /*////////////////////////////////////////////////////////*/
  /**
   * Return index into neighbor table of the given node addr
   * @author terence
   * @param id
   * @return index, if not found return ROUTE_INVALID
   */

  uint8_t findEntry(uint16_t id) {
    uint8_t i = 0;
    for (i = 0; i < ROUTE_TABLE_SIZE; i++) {
      if ((NeighborTbl[i].flags & NBRFLAG_VALID) && NeighborTbl[i].id == id) {
        return i;
      }
    }
    return ROUTE_INVALID;
  }
  /*////////////////////////////////////////////////////////*/
  /**
   * This function determines which entry should be replace
   * in this case, we find the one with the lease send estimate
   * @author terence
   * @param void
   * @return index of the table
   */

  uint8_t findEntryToBeReplaced() {
    uint8_t i = 0;
    uint8_t minSendEst = -1;
    uint8_t minSendEstIndex = ROUTE_INVALID;
    for (i = 0; i < ROUTE_TABLE_SIZE; i++) {
      if ((NeighborTbl[i].flags & NBRFLAG_VALID) == 0) {
        return i;
      }
      if (minSendEst >= NeighborTbl[i].sendEst) {
        minSendEst = NeighborTbl[i].sendEst;
        minSendEstIndex = i;
      }
    }
    return minSendEstIndex;
  }
  /*////////////////////////////////////////////////////////*/
  /**
   * This is going to make a new entry give an index and a id
   * @author terence
   * @param index, the index of the table
   * @param id, the node id 
   * @return void
   */

  void newEntry(uint8_t indes, uint16_t id) {
    NeighborTbl[indes].id = id;
    NeighborTbl[indes].flags = (NBRFLAG_VALID | NBRFLAG_NEW);
    NeighborTbl[indes].liveliness = 0;
    NeighborTbl[indes].parent = ROUTE_INVALID;
    NeighborTbl[indes].cost = ROUTE_INVALID;
    NeighborTbl[indes].childLiveliness = 0;
    NeighborTbl[indes].hop = ROUTE_INVALID;
    NeighborTbl[indes].missed = 0;
    NeighborTbl[indes].received = 0;
    NeighborTbl[indes].receiveEst = 0;
    NeighborTbl[indes].sendEst = 0;
    //call Estimator.clearTrackInfo(NeighborTbl[indes].trackInfo);
  }


  /*////////////////////////////////////////////////////////*/
  /**
   * Get neighbor table entry corresponding to the given address.
   * If current entry doesn't exist, then create one, possibly
   * evicting a previous entry. 
   * XXX - what if it evicts the parent???
   *
   * @author terence
   * @param id, node id
   * @return index
   */

  uint8_t findPreparedIndex(uint16_t id) {
    uint8_t indes = findEntry(id);
    if (indes == (uint8_t) ROUTE_INVALID) {
      indes = findEntryToBeReplaced();
      newEntry(indes, id);
    }
    return indes;
  }


  int sortByReceiveEstFcn(const void *x, const void *y) {
    struct SortEntry *nx = (struct SortEntry *) x;
    struct SortEntry *ny = (struct SortEntry *) y;
    uint8_t xReceiveEst = nx->receiveEst, yReceiveEst = ny->receiveEst;
    if (xReceiveEst > yReceiveEst) return -1;
    if (xReceiveEst == yReceiveEst) return 0;
    if (xReceiveEst < yReceiveEst) return 1;
    return 0; // shouldn't reach here becasue it covers all the cases
  }

  int sortDebugEstFcn(const void *x, const void *y) {
    struct SortDbgEntry *nx = (struct SortDbgEntry *) x;
    struct SortDbgEntry *ny = (struct SortDbgEntry *) y;
    uint8_t xReceiveEst = nx->sendEst, yReceiveEst = ny->sendEst;
    if (xReceiveEst > yReceiveEst) return -1;
    if (xReceiveEst == yReceiveEst) return 0;
    if (xReceiveEst < yReceiveEst) return 1;
    return 0; // shouldn't reach here becasue it covers all the cases
  }

  uint32_t evaluateCost(uint16_t cost, uint8_t sendEst, uint8_t receiveEst) {
    uint32_t transEst = (uint32_t) sendEst * (uint32_t) receiveEst;
    uint32_t immed = ((uint32_t) 1 << 24);

    if (transEst == 0) return ((uint32_t) 1 << (uint32_t) 16);
    // DO NOT change this LINE! mica compiler is WEIRD!
    immed = immed / transEst;
    immed += ((uint32_t) cost << 6);
    return immed;
  }


  void updateEst(TableEntry *Nbr) {
    uint16_t usExpTotal, usActTotal, newAve;

    if (Nbr->flags & NBRFLAG_NEW)
      return;
    
    usExpTotal = ESTIMATE_TO_ROUTE_RATIO;
    //if (pNbr->hop != 0) {
    //  usExpTotal *= (1 + DATA_TO_ROUTE_RATIO);
    //}
    dbg(DBG_ROUTE,"MultiHopWMEWMA: Updating Nbr %d. ExpTotl = %d, rcvd= %d, missed = %d\n",
        Nbr->id, usExpTotal, Nbr->received, Nbr->missed);

    atomic {
      usActTotal = Nbr->received + Nbr->missed;
      
      if (usActTotal < usExpTotal) {
        usActTotal = usExpTotal;
      }
      
      newAve = ((uint16_t) 255 * (uint16_t)Nbr->received) / (uint16_t)usActTotal;
      Nbr->missed = 0;
      Nbr->received = 0;

      // If we haven't seen a recieveEst for us from our neighbor, decay our sendEst
      // exponentially
      if (Nbr->liveliness  == 0) {
        Nbr->sendEst >>= 1;
      }else{
      	Nbr->liveliness --;
      }
    
    }
 

    if (Nbr->flags & NBRFLAG_EST_INIT) {
      uint16_t tmp;
      tmp = ((2 * ((uint16_t)Nbr->receiveEst) + (uint16_t)newAve * 6) / 8);
      Nbr->receiveEst = (uint8_t)tmp;
    }
    else {
      Nbr->receiveEst = (uint8_t) newAve;
      Nbr->flags ^= NBRFLAG_EST_INIT;
    }

     if(Nbr->childLiveliness > 0) Nbr->childLiveliness --;
  }

  void updateTable() {
    TableEntry *pNbr;
    uint8_t i = 0;

    gwEstTicks++;
    gwEstTicks %= ESTIMATE_TO_ROUTE_RATIO;

    for(i = 0; i < ROUTE_TABLE_SIZE; i++) {
      pNbr = &NeighborTbl[i];
      if (pNbr->flags & NBRFLAG_VALID) {
        if (gwEstTicks == 0) 
          updateEst(pNbr);
      }
    }
  }

  bool updateNbrCounters(uint16_t saddr, int16_t seqno, uint8_t *NbrIndex) {
    TableEntry *pNbr;
    int16_t sDelta;
    uint8_t iNbr;
    bool Result = FALSE;  // Result is TRUE if message is a duplicate

    iNbr = findPreparedIndex(saddr);
    pNbr = &NeighborTbl[iNbr];

    sDelta = (seqno - NeighborTbl[iNbr].lastSeqno - 1);

    if (pNbr->flags & NBRFLAG_NEW) {
      pNbr->received++;
      pNbr->lastSeqno = seqno;
      pNbr->flags ^= NBRFLAG_NEW;
    }
    else if (sDelta >= 0) {
      pNbr->missed += sDelta;
      pNbr->received++;
      pNbr->lastSeqno = seqno;
    }
    else if (sDelta < ACCEPTABLE_MISSED) {
      // Something happend to this node.  Reinitialize it's state
      newEntry(iNbr,saddr);
      pNbr->received++;
      pNbr->lastSeqno = seqno;
      pNbr->flags ^= NBRFLAG_NEW;
    }
    else {
      Result = TRUE;
    }

    *NbrIndex = iNbr;
    return Result;

  }

  void chooseParent() {
    TableEntry *pNbr;
    uint32_t ulNbrLinkCost = (uint32_t) -1;
    uint32_t ulNbrTotalCost = (uint32_t) -1;
    uint32_t oldParentCost = (uint32_t) -1;
    uint32_t oldParentLinkCost = (uint32_t) -1;
    uint32_t ulMinTotalCost = (uint32_t) -1;
    TableEntry* pNewParent = NULL;
    TableEntry* pOldParent = NULL;
    uint8_t i;

    if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) return;

    // Choose the parent based on minimal hopcount and cost.  
    // There is a special case for choosing a base-station as it's 
    // receiveEst may be zero (it's not sending any packets)

    for (i = 0;i < ROUTE_TABLE_SIZE;i++) {
      pNbr = &NeighborTbl[i];

      if (!(pNbr->flags & NBRFLAG_VALID)) continue;
      if (pNbr->parent == TOS_LOCAL_ADDRESS) continue;
      if (pNbr->parent == ROUTE_INVALID) continue;
      if (pNbr->hop == ROUTE_INVALID) continue;
      if (pNbr->cost == (uint16_t) ROUTE_INVALID) continue;
      if (pNbr->sendEst < 25 || pNbr->receiveEst < 25) continue;
      if (pNbr->childLiveliness > 0) continue;

      ulNbrLinkCost = evaluateCost(0, pNbr->sendEst,pNbr->receiveEst);
      ulNbrTotalCost = evaluateCost(pNbr->cost, pNbr->sendEst,pNbr->receiveEst);

      call Leds.greenToggle();
      if (ulNbrLinkCost > MAX_ALLOWABLE_LINK_COST) continue;
      dbg(DBG_ROUTE,"MultiHopWMEWMA node: %d, Cost %d, link Cost, %d\n", pNbr->id, ulNbrTotalCost, ulNbrLinkCost);
      if (pNbr == gpCurrentParent) {
	pOldParent = pNbr;
  	oldParentCost = ulNbrTotalCost;
  	oldParentLinkCost = ulNbrLinkCost;
  	continue;
      }
      
      if (ulMinTotalCost > ulNbrTotalCost) {
        ulMinTotalCost = ulNbrTotalCost;
        pNewParent = pNbr;
      }

    }

    //now pick between old and new.
    if(pNewParent == NULL) {
	//use the old parent unless it is null;
	pNewParent = pOldParent;
        ulMinTotalCost = oldParentCost;
    } else if((pOldParent != NULL) &&
              (oldParentCost < (SWITCH_THRESHOLD + ulMinTotalCost))){
	//both valid, but use the old parent 
	pNewParent = pOldParent;
        ulMinTotalCost = oldParentCost;
    }

    if (pNewParent) {
      atomic {
        gpCurrentParent = pNewParent;
        gbCurrentHopCount = pNewParent->hop + 1;
        gbCurrentCost = ulMinTotalCost >> 6;
      }
    } else {
      atomic {
        gpCurrentParent = NULL;
        gbCurrentHopCount = ROUTE_INVALID;
        gbCurrentCost = ROUTE_INVALID;
      }

    }
  }

  uint8_t last_entry_sent;

  task void SendRouteTask() {
    TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *) &routeMsg.data[0];
    RoutePacket *pRP = (RoutePacket *)&pMHMsg->data[0];
    uint8_t length = offsetof(TOS_MHopMsg,data) + offsetof(RoutePacket,estList);
    uint8_t maxEstEntries;
    uint8_t i,j;
    uint8_t last_index_added = 0;

    if (gfSendRouteBusy) {
      return;
    }

    dbg(DBG_ROUTE,"MultiHopWMEWMA Sending route update msg.\n");
    dbg(DBG_ROUTE,"Current cost: %d.\n", gbCurrentCost);

    maxEstEntries = TOSH_DATA_LENGTH - length;
    maxEstEntries = maxEstEntries / sizeof(RPEstEntry);


    pRP->parent = (gpCurrentParent) ? gpCurrentParent->id : ROUTE_INVALID;
    pRP->cost = gbCurrentCost; 

    for (i = 0,j = 0;i < ROUTE_TABLE_SIZE && j < maxEstEntries; i++) {
      uint8_t table_index = i + last_entry_sent + 1;
      if(table_index >= ROUTE_TABLE_SIZE) table_index -=ROUTE_TABLE_SIZE;
      if (NeighborTbl[table_index].flags & NBRFLAG_VALID && NeighborTbl[table_index].receiveEst > 100) {
        pRP->estList[j].id = NeighborTbl[table_index].id;
        pRP->estList[j].receiveEst = NeighborTbl[table_index].receiveEst;
	j ++;
        length += sizeof(RPEstEntry);
	last_index_added = table_index;
        dbg(DBG_ROUTE,"Adding %d to route msg.\n", pRP->estList[j].id);
      }
    }
    last_entry_sent = last_index_added;
    dbg(DBG_ROUTE,"Added total of %d entries to route msg.\n", j);
    pRP->estEntries = j;
    pMHMsg->sourceaddr = pMHMsg->originaddr = TOS_LOCAL_ADDRESS;
    pMHMsg->hopcount = gbCurrentHopCount;
    pMHMsg->seqno = gCurrentSeqNo++;

    if (call SendMsg.send(TOS_BCAST_ADDR, length, &routeMsg) == SUCCESS) {
      gfSendRouteBusy = TRUE;
    }

  }


#ifdef MULTI_HOP_DEBUG
  task void SendDebugTask() {
    struct SortDbgEntry sortTbl[ROUTE_TABLE_SIZE];
    uint16_t max_length;
    uint8_t length = offsetof(DebugPacket,estList);
    DebugPacket *pRP = (DebugPacket *)call DebugSendMsg.getBuffer(&debugMsg,&max_length);
    uint8_t maxEstEntries;
    uint16_t parent;
    uint8_t i,j;

    dbg(DBG_ROUTE,"MultiHopWMEWMA Sending route debug msg.\n");

    maxEstEntries = max_length / sizeof(DBGEstEntry);
    maxEstEntries --;
    parent = (gpCurrentParent) ? gpCurrentParent->id : ROUTE_INVALID;

    for (i = 0,j = 0;i < ROUTE_TABLE_SIZE; i++) {
      if (NeighborTbl[i].flags & NBRFLAG_VALID && NeighborTbl[i].id != parent) {
        sortTbl[j].id = NeighborTbl[i].id;
        sortTbl[j].sendEst = NeighborTbl[i].sendEst;
        sortTbl[j].hopcount = NeighborTbl[i].hop;
        j++;
      }
    }
    qsort (sortTbl,j,sizeof(struct SortDbgEntry),sortDebugEstFcn);

    pRP->estEntries = (j > maxEstEntries) ? maxEstEntries : j;
    pRP->estList[0].id = parent;
    if(gpCurrentParent){
	pRP->estList[0].sendEst = gpCurrentParent->sendEst;
	pRP->estList[0].hopcount = gpCurrentParent->hop;
    }
    length += sizeof(DBGEstEntry);

    for (i = 0; i < pRP->estEntries; i++) {
      pRP->estList[i+1].id = sortTbl[i].id;
      pRP->estList[i+1].sendEst = sortTbl[i].sendEst;
      pRP->estList[i+1].hopcount = sortTbl[i].hopcount;
      length += sizeof(DBGEstEntry);
    }
    pRP->estEntries ++;
    call DebugSendMsg.send(&debugMsg, length);

  }

  int debugCounter;
#endif

  task void TimerTask() {

    call Leds.redToggle();
    dbg(DBG_ROUTE,"MultiHopWMEWMA timer task.\n");
    updateTable();

#ifndef NDEBUG
    {
      int i;
      dbg(DBG_ROUTE,"\taddr\tprnt\tcost\tmisd\trcvd\tlstS\thop\trEst\tsEst\tDesc\n");
      for (i = 0;i < ROUTE_TABLE_SIZE;i++) {
        if (NeighborTbl[i].flags) {
          dbg(DBG_ROUTE,"\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
              NeighborTbl[i].id,
              NeighborTbl[i].parent,
              NeighborTbl[i].cost,
              NeighborTbl[i].missed,
              NeighborTbl[i].received,
              NeighborTbl[i].lastSeqno,
              NeighborTbl[i].hop,
              NeighborTbl[i].receiveEst,
              NeighborTbl[i].sendEst,
              NeighborTbl[i].childLiveliness);
        }
      }
      if (gpCurrentParent) {
        dbg(DBG_ROUTE,"MultiHopWMEWMA: Parent = %d\n",gpCurrentParent->id);
      }
    }
#endif
    chooseParent();
#ifdef MULTI_HOP_DEBUG
    if(TOS_LOCAL_ADDRESS != BASE_STATION_ADDRESS) debugCounter ++;
    if(debugCounter > 1){
	post SendDebugTask();
	debugCounter = 0;
    }else{
#endif //MULTI_HOP_DEBUG
      call ATimer.start(TIMER_ONE_SHOT, 32);
      //post SendRouteTask();
#ifdef MULTI_HOP_DEBUG
    }
#endif //MULTI_HOP_DEBUG

  }

  event result_t ATimer.fired(){
    post SendRouteTask();
    return SUCCESS;
  }

  command result_t StdControl.init() {

    memset((void *)NeighborTbl,0,(sizeof(TableEntry) * ROUTE_TABLE_SIZE));
    BaseStation.id = TOS_UART_ADDR;
    BaseStation.parent = TOS_UART_ADDR;
    BaseStation.flags = NBRFLAG_VALID;
    BaseStation.hop = 0;
    gpCurrentParent = NULL;
    gbCurrentHopCount = ROUTE_INVALID;
    gCurrentSeqNo = 0;
    gwEstTicks = 0;
    gUpdateInterval = DATA_TO_ROUTE_RATIO * DATA_FREQ;
    gfSendRouteBusy = FALSE;
    gSelfTimer = TRUE;

    fixedRoute = FALSE;

    if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) {

      gpCurrentParent = &BaseStation;
      gbCurrentHopCount = 0;
      gbCurrentCost = 0;

    }

    return SUCCESS;
  }

  command result_t StdControl.start() {
    if (gSelfTimer){
      post TimerTask();
      call Timer.start(TIMER_REPEAT,gUpdateInterval);
#ifdef USE_WATCHDOG
	  call PoochHandler.start();
	  call WDT.start(gUpdateInterval * 5);
#endif
    }
    //  post TimerTask();
    //  call Timer.start(TIMER_REPEAT,gUpdateInterval);
    //}
    //call Leds.redToggle();
    return SUCCESS;
  }

  command result_t StdControl.stop() {
    call Timer.stop();
    return SUCCESS;
  }

  command bool RouteSelect.isActive() {
#if 0
    bool Result = FALSE;

    if (gpCurrentParent != NULL) {
      Result = TRUE;
    }

    return Result;
#endif

    return TRUE;
  }


  void updateDescendant(uint16_t id){
	uint8_t indes = findEntry(id);
	if (indes == (uint8_t) ROUTE_INVALID) { return;}
	else{
		NeighborTbl[indes].childLiveliness = MAX_DESCENDANT_LIVE;
	}
  }

  command result_t RouteSelect.selectRoute(TOS_MsgPtr Msg, uint8_t id) {
    TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];

    uint8_t iNbr;
    bool fIsDuplicate;
    result_t Result = SUCCESS;


    if (!fixedRoute && (gpCurrentParent == NULL)) {
      // If the msg is locally generated, then send it to the broadcast address
      // This is necessary to seed the network.
      if ((pMHMsg->sourceaddr == TOS_LOCAL_ADDRESS) &&
          (pMHMsg->originaddr == TOS_LOCAL_ADDRESS)) {
        pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
        pMHMsg->hopcount = fixedRoute ? fixedDepth : gbCurrentHopCount;
        pMHMsg->seqno = gCurrentSeqNo++;
        Msg->addr = TOS_BCAST_ADDR;
        return SUCCESS;
      }
      else {
        return FAIL;
      }
    }

    if (((!fixedRoute) && (gbCurrentHopCount >= pMHMsg->hopcount))
      ||((fixedRoute) && (fixedDepth >= pMHMsg->hopcount))) {
      // Possible cycle??
      return FAIL;
    }
    
    if ((pMHMsg->sourceaddr == TOS_LOCAL_ADDRESS) &&
        (pMHMsg->originaddr == TOS_LOCAL_ADDRESS)) {
      fIsDuplicate = FALSE;
    }
    else {
      fIsDuplicate = updateNbrCounters(pMHMsg->sourceaddr,pMHMsg->seqno,&iNbr);
    }

    if (!fIsDuplicate) {
      pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
      pMHMsg->hopcount = fixedRoute ? fixedDepth : gbCurrentHopCount;
      if ((!fixedRoute && (gpCurrentParent->id != TOS_UART_ADDR))
        || (fixedRoute && (fixedParent != TOS_UART_ADDR))) {
        pMHMsg->seqno = gCurrentSeqNo++;
      }
      Msg->addr = fixedRoute ? fixedParent : gpCurrentParent->id;
      if(pMHMsg->originaddr != TOS_LOCAL_ADDRESS){
	  updateDescendant(pMHMsg->originaddr);
      }
    }
    else {
      Result = FAIL;
    }
    dbg(DBG_ROUTE,"MultiHopWMEWMA: Sequence Number: %d\n", pMHMsg->seqno);

    return Result;

  }

  command result_t RouteSelect.initializeFields(TOS_MsgPtr Msg, uint8_t id) {
    TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];

    pMHMsg->sourceaddr = pMHMsg->originaddr = TOS_LOCAL_ADDRESS;
    pMHMsg->hopcount = ROUTE_INVALID;

    return SUCCESS;
  }

  command uint8_t* RouteSelect.getBuffer(TOS_MsgPtr Msg, uint16_t* Len) {

  }

  command uint16_t FixRoute.getParent() {

    uint16_t addr;

    addr = (gpCurrentParent != NULL) ? gpCurrentParent->id : 0xffff;

    return addr;
  }
  command uint16_t RouteControl.getParent() {
    return fixedRoute ? fixedParent : call FixRoute.getParent();
  }

  command uint8_t RouteControl.getQuality() {
    uint8_t val;

    val = (gpCurrentParent != NULL) ? gpCurrentParent->sendEst : 0x00;

    return val;
  }

  command uint8_t FixRoute.getDepth() {
    return gbCurrentHopCount;
  }
  command uint8_t RouteControl.getDepth() {
    return fixedRoute ? fixedDepth : call FixRoute.getDepth();
  }

  command uint8_t RouteControl.getOccupancy() {
    return 0;
  }

  command uint16_t RouteControl.getSender(TOS_MsgPtr msg) {
    TOS_MHopMsg		*pMHMsg = (TOS_MHopMsg *)msg->data;
    return pMHMsg->sourceaddr;
  }

  command result_t RouteControl.setUpdateInterval(uint16_t Interval) {
    result_t Result;

    call Timer.stop();
    gUpdateInterval = (Interval * 1024L);  // * 1024 to make the math simpler
	gSelfTimer = TRUE;
    Result = call Timer.start(TIMER_REPEAT,gUpdateInterval);
#ifdef USE_WATCHDOG
	call PoochHandler.stop();
	call PoochHandler.start();
	call WDT.start(gUpdateInterval * 5);
#endif

    return Result;
  }

  command result_t RouteControl.manualUpdate() {
    result_t Result;
    
    gSelfTimer = FALSE;
    call Timer.stop();
    Result = post TimerTask();
    return Result;
  }



  event result_t Timer.fired() {
    post TimerTask();
    return SUCCESS;
  }

  event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr Msg) {
    TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
    RoutePacket *pRP = (RoutePacket *)&pMHMsg->data[0];
    uint16_t saddr;
    uint8_t i, iNbr;

    call Leds.yellowToggle();
#ifdef USE_WATCHDOG
	call WDT.reset();
#endif

    saddr = pMHMsg->sourceaddr;

    updateNbrCounters(saddr,pMHMsg->seqno,&iNbr);
    //    iNbr = findPreparedIndex(saddr);

    NeighborTbl[iNbr].parent = pRP->parent;
    NeighborTbl[iNbr].hop = pMHMsg->hopcount;
    NeighborTbl[iNbr].cost = pRP->cost;

    // If it is no longer my child, clear it
    if (NeighborTbl[iNbr].childLiveliness > 0 && pRP->parent != TOS_LOCAL_ADDRESS)
      NeighborTbl[iNbr].childLiveliness = 0;

    // find out my address, extract the estimation
    for (i = 0; i < pRP->estEntries; i++) {
      if (pRP->estList[i].id == TOS_LOCAL_ADDRESS) {
        NeighborTbl[iNbr].sendEst = pRP->estList[i].receiveEst;
        NeighborTbl[iNbr].liveliness = LIVELINESS;
      }
    }

    return Msg;
  }
  
  event result_t Snoop.intercept[uint8_t id](TOS_MsgPtr Msg, void *Payload, uint16_t Len) {
    TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
    uint8_t iNbr;

    updateNbrCounters(pMHMsg->sourceaddr,pMHMsg->seqno,&iNbr);
    
    // Extract routing information if we know this is a multihop message
    // Something in the future.

    return SUCCESS;
  }


  event result_t SendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
    gfSendRouteBusy = FALSE;

    return SUCCESS;
  }
  event result_t DebugSendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
    return SUCCESS;
  }

  command result_t FixRoute.fix() {
    if (fixedRoute) return SUCCESS;
    fixedRoute = TRUE;
    fixedParent = gpCurrentParent->id;
    fixedDepth = gbCurrentHopCount;
    return SUCCESS;
  }
  command result_t FixRoute.release() {
    fixedRoute = FALSE;
    return SUCCESS;
  }
  command uint8_t FixRoute.getFixedRoute() {
    return fixedRoute ? 1 : 0;
  }

}


--- NEW FILE: README ---
# Please contact tinyos-help at millennium.berkeley.edu for 
# questions or bug reports.  Any other suggestions or feedback 
# can be sent to us: 
# Philip Buonadonna (pbuonado at intel-research.net) or 
# Alec Woo (awoo at cs.berkeley.edu) 
#                               November 20th, 2003.

Important parameters to tune in MultihopWMEWMA.nc

    BASE_STATION_ADDRESS        = 0,
    ROUTE_TABLE_SIZE            = 16,
    ESTIMATE_TO_ROUTE_RATIO     = 10,
    DATA_TO_ROUTE_RATIO         = 2,
    DATA_FREQ                   = 10000,
    SWITCH_THRESHOLD     	= 192,
    MAX_DESCENDANT		= 5

In this protocol, the minimum message rate is defined by route message
rate, which is a ratio of the data rate defined by
DATA_TO_ROUTE_RATIO.  For example, if DATA_FREQ is 10000 (~ 1
packet/10 sec) and DATA_TO_ROUTE_RATIO is 2, the route message
is will be 20000 (~ 1 msg/20sec).  This rate is tunable and
will affect network load and rate of adaptation to changes.

ESTIMATE_TO_ROUTE is a parameter that defines the time window
T for WMEWMA estimator.  If it is set to 10, it means that
an estimation will be performed every ten route message time.

SWITCH_THRESHOLD is a parameter to define a noise margin for
switching to a better parent.  It is a scaled value. To convert
it to the number of transmission, simply divide it by 256.  
In this case, 192/256 = 0.75.  That is, we only switch to a 
new parent if its cost is 0.75 lower than our current parent.

MAX_DESCENDADNT_LIVE is used as a paremter to time out children
in the neighbor table. 5 means a child 

Notice that chooseParent() is called on a periodic basis as
a route damping mechanism.  The period is the same as the
route message rate.  

The current route table managment is a simple filtering
mechanism based on send (outbound) link estimations.

--- NEW FILE: WMEWMAMultiHopRouter.nc ---
includes MultiHop;

configuration WMEWMAMultiHopRouter {
  
  provides {
    interface StdControl;
    // The interface are as parameterised by the active message id
	// only the 10 active message ids defined MultiHop.h are supported.
    interface Receive[uint8_t id];
    interface Intercept[uint8_t id];
    interface Intercept as Snoop[uint8_t id];
    interface Send[uint8_t id];
    interface RouteControl;
  }

  uses {
    interface ReceiveMsg[uint8_t id];
  }

}

implementation {
  
  // Uncomment for use with mh6
  components MultiHopEngineM, MultiHopWMEWMA, GenericCommPromiscuous as Comm, 
    QueuedSend, TimerC, 
#ifdef USE_WATCHDOG
	WDTC,
#endif
	NoLeds;

  StdControl = MultiHopEngineM;
  Receive = MultiHopEngineM;
  Send = MultiHopEngineM;
  Intercept = MultiHopEngineM.Intercept;
  Snoop = MultiHopEngineM.Snoop;
  RouteControl = MultiHopEngineM;

  ReceiveMsg = MultiHopEngineM;

  MultiHopEngineM.SubControl -> QueuedSend.StdControl;
  MultiHopEngineM.SubControl -> MultiHopWMEWMA.StdControl;
  MultiHopEngineM.CommStdControl -> Comm;
  MultiHopEngineM.CommControl -> Comm;
  MultiHopEngineM.RouteSelectCntl -> MultiHopWMEWMA.RouteControl;
  MultiHopEngineM.RouteSelect -> MultiHopWMEWMA;


  MultiHopEngineM.SendMsg -> QueuedSend.SendMsg;
  
  MultiHopWMEWMA.Timer -> TimerC.Timer[unique("Timer")];  
  MultiHopWMEWMA.ATimer -> TimerC.Timer[unique("Timer")];  
  MultiHopWMEWMA.ReceiveMsg -> Comm.ReceiveMsg[AM_MULTIHOPMSG];
  MultiHopWMEWMA.Snoop -> MultiHopEngineM.Snoop;
  MultiHopWMEWMA.SendMsg -> QueuedSend.SendMsg[AM_MULTIHOPMSG];
  MultiHopWMEWMA.DebugSendMsg -> MultiHopEngineM.Send[3];
  MultiHopEngineM.ReceiveMsg[3] -> Comm.ReceiveMsg[3];
  MultiHopWMEWMA.Leds -> NoLeds;
#ifdef USE_WATCHDOG
  MultiHopWMEWMA.PoochHandler -> WDTC.StdControl;
  MultiHopWMEWMA.WDT -> WDTC.WDT;
#endif
}



More information about the Tinyos-contrib-commits mailing list