MultiHopWMEWMA.nc
上传用户:joranyuan
上传日期:2022-06-23
资源大小:3306k
文件大小:23k
源码类别:

网络

开发平台:

Others

  1. // $Id: MultiHopWMEWMA.nc,v 1.10 2005/04/28 19:25:05 jwhui Exp $
  2. /* tab:4
  3.  * "Copyright (c) 2000-2003 The Regents of the University  of California.  
  4.  * All rights reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose, without fee, and without written agreement is
  8.  * hereby granted, provided that the above copyright notice, the following
  9.  * two paragraphs and the author appear in all copies of this software.
  10.  * 
  11.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  12.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  13.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  14.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  15.  * 
  16.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  17.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  18.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  19.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  20.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
  21.  *
  22.  * Copyright (c) 2002-2003 Intel Corporation
  23.  * All rights reserved.
  24.  *
  25.  * This file is distributed under the terms in the attached INTEL-LICENSE     
  26.  * file. If you do not find these files, copies can be found by writing to
  27.  * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
  28.  * 94704.  Attention:  Intel License Inquiry.
  29.  */
  30. /*
  31.  *
  32.  * Authors: Philip Buonadonna, Alec Woo, Terence Tong, Crossbow
  33.  * Date last modified:  2/20/03
  34.  *
  35.  */
  36. includes AM;
  37. includes MultiHop;
  38. //#define MULTI_HOP_DEBUG 1
  39. module MultiHopWMEWMA {
  40.   provides {
  41.     interface StdControl;
  42.     interface RouteSelect;
  43.     interface RouteControl;
  44.   }
  45.   uses {
  46.     interface Leds;
  47.     interface Timer;
  48.     interface Timer as ATimer;
  49.     interface ReceiveMsg;
  50.     interface Intercept as Snoop[uint8_t id];
  51.     interface SendMsg;
  52.     interface Send as DebugSendMsg;
  53. #ifdef USE_WATCHDOG
  54. interface StdControl as PoochHandler;
  55. interface WDT;
  56. #endif
  57.   }
  58. }
  59. implementation {
  60.   enum {
  61.     NBRFLAG_VALID    = 0x01,
  62.     NBRFLAG_NEW      = 0x02,
  63.     NBRFLAG_EST_INIT = 0x04
  64.   };
  65.   enum {
  66.     BASE_STATION_ADDRESS        = 0,
  67.     ROUTE_TABLE_SIZE            = 16,
  68.     ESTIMATE_TO_ROUTE_RATIO     = 10,
  69.     ACCEPTABLE_MISSED           = -20,
  70.     DATA_TO_ROUTE_RATIO         = 1,
  71.     DATA_FREQ                   = 8192,
  72.     SWITCH_THRESHOLD      = 384,
  73.     MAX_ALLOWABLE_LINK_COST     = 256*6,
  74.     LIVELINESS               = 5,
  75.     MAX_DESCENDANT_LIVE = 5
  76.   };
  77.   enum {
  78.     ROUTE_INVALID    = 0xff
  79.   };
  80.   struct SortEntry {
  81.     uint16_t id;
  82.     uint8_t  receiveEst;
  83.   };
  84.   struct SortDbgEntry {
  85.     uint16_t id;
  86.     uint8_t  sendEst;
  87.     uint8_t  hopcount; 
  88.   };
  89.   typedef struct RPEstEntry {
  90.     uint16_t id;
  91.     uint8_t receiveEst;
  92.   } __attribute__ ((packed)) RPEstEntry;
  93.   typedef struct RoutePacket {
  94.     uint16_t parent;
  95.     uint16_t cost;
  96.     uint8_t estEntries;
  97.     RPEstEntry estList[1];
  98.   } __attribute__ ((packed)) RoutePacket;
  99.   typedef struct TableEntry {
  100.     uint16_t id;  // Node Address
  101.     uint16_t parent;
  102.     uint16_t cost;
  103.     uint8_t childLiveliness;
  104.     uint16_t missed;
  105.     uint16_t received;
  106.     int16_t lastSeqno;
  107.     uint8_t flags;
  108.     uint8_t liveliness;
  109.     uint8_t hop;
  110.     uint8_t receiveEst;
  111.     uint8_t sendEst;
  112.   } TableEntry;
  113.   TOS_Msg debugMsg; 
  114.   TOS_Msg routeMsg; 
  115.   bool gfSendRouteBusy;
  116.   bool gSelfTimer;
  117.   TableEntry BaseStation;
  118.   TableEntry NeighborTbl[ROUTE_TABLE_SIZE];
  119.   TableEntry *gpCurrentParent;
  120.   uint8_t gbCurrentHopCount;
  121.   uint16_t gbCurrentCost;
  122.   int16_t gCurrentSeqNo;
  123.   uint16_t gwEstTicks;
  124.   uint32_t gUpdateInterval;
  125.   /*////////////////////////////////////////////////////////*/
  126.   /**
  127.    * Return index into neighbor table of the given node addr
  128.    * @author terence
  129.    * @param id
  130.    * @return index, if not found return ROUTE_INVALID
  131.    */
  132.   uint8_t findEntry(uint16_t id) {
  133.     uint8_t i = 0;
  134.     for (i = 0; i < ROUTE_TABLE_SIZE; i++) {
  135.       if ((NeighborTbl[i].flags & NBRFLAG_VALID) && NeighborTbl[i].id == id) {
  136.         return i;
  137.       }
  138.     }
  139.     return ROUTE_INVALID;
  140.   }
  141.   /*////////////////////////////////////////////////////////*/
  142.   /**
  143.    * This function determines which entry should be replace
  144.    * in this case, we find the one with the lease send estimate
  145.    * @author terence
  146.    * @param void
  147.    * @return index of the table
  148.    */
  149.   uint8_t findEntryToBeReplaced() {
  150.     uint8_t i = 0;
  151.     uint8_t minSendEst = -1;
  152.     uint8_t minSendEstIndex = ROUTE_INVALID;
  153.     for (i = 0; i < ROUTE_TABLE_SIZE; i++) {
  154.       if ((NeighborTbl[i].flags & NBRFLAG_VALID) == 0) {
  155.         return i;
  156.       }
  157.       if (minSendEst >= NeighborTbl[i].sendEst) {
  158.         minSendEst = NeighborTbl[i].sendEst;
  159.         minSendEstIndex = i;
  160.       }
  161.     }
  162.     return minSendEstIndex;
  163.   }
  164.   /*////////////////////////////////////////////////////////*/
  165.   /**
  166.    * This is going to make a new entry give an index and a id
  167.    * @author terence
  168.    * @param index, the index of the table
  169.    * @param id, the node id 
  170.    * @return void
  171.    */
  172.   void newEntry(uint8_t indes, uint16_t id) {
  173.     NeighborTbl[indes].id = id;
  174.     NeighborTbl[indes].flags = (NBRFLAG_VALID | NBRFLAG_NEW);
  175.     NeighborTbl[indes].liveliness = 0;
  176.     NeighborTbl[indes].parent = ROUTE_INVALID;
  177.     NeighborTbl[indes].cost = ROUTE_INVALID;
  178.     NeighborTbl[indes].childLiveliness = 0;
  179.     NeighborTbl[indes].hop = ROUTE_INVALID;
  180.     NeighborTbl[indes].missed = 0;
  181.     NeighborTbl[indes].received = 0;
  182.     NeighborTbl[indes].receiveEst = 0;
  183.     NeighborTbl[indes].sendEst = 0;
  184.     //call Estimator.clearTrackInfo(NeighborTbl[indes].trackInfo);
  185.   }
  186.   /*////////////////////////////////////////////////////////*/
  187.   /**
  188.    * Get neighbor table entry corresponding to the given address.
  189.    * If current entry doesn't exist, then create one, possibly
  190.    * evicting a previous entry. 
  191.    * XXX - what if it evicts the parent???
  192.    *
  193.    * @author terence
  194.    * @param id, node id
  195.    * @return index
  196.    */
  197.   uint8_t findPreparedIndex(uint16_t id) {
  198.     uint8_t indes = findEntry(id);
  199.     if (indes == (uint8_t) ROUTE_INVALID) {
  200.       indes = findEntryToBeReplaced();
  201.       newEntry(indes, id);
  202.     }
  203.     return indes;
  204.   }
  205.   int sortByReceiveEstFcn(const void *x, const void *y) {
  206.     struct SortEntry *nx = (struct SortEntry *) x;
  207.     struct SortEntry *ny = (struct SortEntry *) y;
  208.     uint8_t xReceiveEst = nx->receiveEst, yReceiveEst = ny->receiveEst;
  209.     if (xReceiveEst > yReceiveEst) return -1;
  210.     if (xReceiveEst == yReceiveEst) return 0;
  211.     if (xReceiveEst < yReceiveEst) return 1;
  212.     return 0; // shouldn't reach here becasue it covers all the cases
  213.   }
  214.   int sortDebugEstFcn(const void *x, const void *y) {
  215.     struct SortDbgEntry *nx = (struct SortDbgEntry *) x;
  216.     struct SortDbgEntry *ny = (struct SortDbgEntry *) y;
  217.     uint8_t xReceiveEst = nx->sendEst, yReceiveEst = ny->sendEst;
  218.     if (xReceiveEst > yReceiveEst) return -1;
  219.     if (xReceiveEst == yReceiveEst) return 0;
  220.     if (xReceiveEst < yReceiveEst) return 1;
  221.     return 0; // shouldn't reach here becasue it covers all the cases
  222.   }
  223.   uint32_t evaluateCost(uint16_t cost, uint8_t sendEst, uint8_t receiveEst) {
  224.     uint32_t transEst = (uint32_t) sendEst * (uint32_t) receiveEst;
  225.     uint32_t immed = ((uint32_t) 1 << 24);
  226.     if (transEst == 0) return ((uint32_t) 1 << (uint32_t) 16);
  227.     // DO NOT change this LINE! mica compiler is WEIRD!
  228.     immed = immed / transEst;
  229.     immed += ((uint32_t) cost << 6);
  230.     return immed;
  231.   }
  232.   void updateEst(TableEntry *Nbr) {
  233.     uint16_t usExpTotal, usActTotal, newAve;
  234.     if (Nbr->flags & NBRFLAG_NEW)
  235.       return;
  236.     
  237.     usExpTotal = ESTIMATE_TO_ROUTE_RATIO;
  238.     //if (pNbr->hop != 0) {
  239.     //  usExpTotal *= (1 + DATA_TO_ROUTE_RATIO);
  240.     //}
  241.     dbg(DBG_ROUTE,"MultiHopWMEWMA: Updating Nbr %d. ExpTotl = %d, rcvd= %d, missed = %dn",
  242.         Nbr->id, usExpTotal, Nbr->received, Nbr->missed);
  243.     atomic {
  244.       usActTotal = Nbr->received + Nbr->missed;
  245.       
  246.       if (usActTotal < usExpTotal) {
  247.         usActTotal = usExpTotal;
  248.       }
  249.       
  250.       newAve = ((uint16_t) 255 * (uint16_t)Nbr->received) / (uint16_t)usActTotal;
  251.       Nbr->missed = 0;
  252.       Nbr->received = 0;
  253.       // If we haven't seen a recieveEst for us from our neighbor, decay our sendEst
  254.       // exponentially
  255.       if (Nbr->liveliness  == 0) {
  256.         Nbr->sendEst >>= 1;
  257.       }else{
  258.        Nbr->liveliness --;
  259.       }
  260.     
  261.     }
  262.  
  263.     if (Nbr->flags & NBRFLAG_EST_INIT) {
  264.       uint16_t tmp;
  265.       tmp = ((2 * ((uint16_t)Nbr->receiveEst) + (uint16_t)newAve * 6) / 8);
  266.       Nbr->receiveEst = (uint8_t)tmp;
  267.     }
  268.     else {
  269.       Nbr->receiveEst = (uint8_t) newAve;
  270.       Nbr->flags ^= NBRFLAG_EST_INIT;
  271.     }
  272.      if(Nbr->childLiveliness > 0) Nbr->childLiveliness --;
  273.   }
  274.   void updateTable() {
  275.     TableEntry *pNbr;
  276.     uint8_t i = 0;
  277.     gwEstTicks++;
  278.     gwEstTicks %= ESTIMATE_TO_ROUTE_RATIO;
  279.     for(i = 0; i < ROUTE_TABLE_SIZE; i++) {
  280.       pNbr = &NeighborTbl[i];
  281.       if (pNbr->flags & NBRFLAG_VALID) {
  282.         if (gwEstTicks == 0) 
  283.           updateEst(pNbr);
  284.       }
  285.     }
  286.   }
  287.   bool updateNbrCounters(uint16_t saddr, int16_t seqno, uint8_t *NbrIndex) {
  288.     TableEntry *pNbr;
  289.     int16_t sDelta;
  290.     uint8_t iNbr;
  291.     bool Result = FALSE;  // Result is TRUE if message is a duplicate
  292.     iNbr = findPreparedIndex(saddr);
  293.     pNbr = &NeighborTbl[iNbr];
  294.     sDelta = (seqno - NeighborTbl[iNbr].lastSeqno - 1);
  295.     if (pNbr->flags & NBRFLAG_NEW) {
  296.       pNbr->received++;
  297.       pNbr->lastSeqno = seqno;
  298.       pNbr->flags ^= NBRFLAG_NEW;
  299.     }
  300.     else if (sDelta >= 0) {
  301.       pNbr->missed += sDelta;
  302.       pNbr->received++;
  303.       pNbr->lastSeqno = seqno;
  304.     }
  305.     else if (sDelta < ACCEPTABLE_MISSED) {
  306.       // Something happend to this node.  Reinitialize it's state
  307.       newEntry(iNbr,saddr);
  308.       pNbr->received++;
  309.       pNbr->lastSeqno = seqno;
  310.       pNbr->flags ^= NBRFLAG_NEW;
  311.     }
  312.     else {
  313.       Result = TRUE;
  314.     }
  315.     *NbrIndex = iNbr;
  316.     return Result;
  317.   }
  318.   void chooseParent() {
  319.     TableEntry *pNbr;
  320.     uint32_t ulNbrLinkCost = (uint32_t) -1;
  321.     uint32_t ulNbrTotalCost = (uint32_t) -1;
  322.     uint32_t oldParentCost = (uint32_t) -1;
  323.     uint32_t oldParentLinkCost = (uint32_t) -1;
  324.     uint32_t ulMinTotalCost = (uint32_t) -1;
  325.     TableEntry* pNewParent = NULL;
  326.     TableEntry* pOldParent = NULL;
  327.     uint8_t i;
  328.     if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) return;
  329.     // Choose the parent based on minimal hopcount and cost.  
  330.     // There is a special case for choosing a base-station as it's 
  331.     // receiveEst may be zero (it's not sending any packets)
  332.     for (i = 0;i < ROUTE_TABLE_SIZE;i++) {
  333.       pNbr = &NeighborTbl[i];
  334.       if (!(pNbr->flags & NBRFLAG_VALID)) continue;
  335.       if (pNbr->parent == TOS_LOCAL_ADDRESS) continue;
  336.       if (pNbr->parent == ROUTE_INVALID) continue;
  337.       if (pNbr->hop == ROUTE_INVALID) continue;
  338.       if (pNbr->cost == (uint16_t) ROUTE_INVALID) continue;
  339.       if (pNbr->sendEst < 25 || pNbr->receiveEst < 25) continue;
  340.       if (pNbr->childLiveliness > 0) continue;
  341.       ulNbrLinkCost = evaluateCost(0, pNbr->sendEst,pNbr->receiveEst);
  342.       ulNbrTotalCost = evaluateCost(pNbr->cost, pNbr->sendEst,pNbr->receiveEst);
  343.       call Leds.greenToggle();
  344.       if (ulNbrLinkCost > MAX_ALLOWABLE_LINK_COST) continue;
  345.       dbg(DBG_ROUTE,"MultiHopWMEWMA node: %d, Cost %d, link Cost, %dn", pNbr->id, ulNbrTotalCost, ulNbrLinkCost);
  346.       if (pNbr == gpCurrentParent) {
  347. pOldParent = pNbr;
  348.    oldParentCost = ulNbrTotalCost;
  349.    oldParentLinkCost = ulNbrLinkCost;
  350.    continue;
  351.       }
  352.       
  353.       if (ulMinTotalCost > ulNbrTotalCost) {
  354.         ulMinTotalCost = ulNbrTotalCost;
  355.         pNewParent = pNbr;
  356.       }
  357.     }
  358.     //now pick between old and new.
  359.     if(pNewParent == NULL) {
  360. //use the old parent unless it is null;
  361. pNewParent = pOldParent;
  362.         ulMinTotalCost = oldParentCost;
  363.     } else if((pOldParent != NULL) &&
  364.               (oldParentCost < (SWITCH_THRESHOLD + ulMinTotalCost))){
  365. //both valid, but use the old parent 
  366. pNewParent = pOldParent;
  367.         ulMinTotalCost = oldParentCost;
  368.     }
  369.     if (pNewParent) {
  370.       atomic {
  371.         gpCurrentParent = pNewParent;
  372.         gbCurrentHopCount = pNewParent->hop + 1;
  373.         gbCurrentCost = ulMinTotalCost >> 6;
  374.       }
  375.     } else {
  376.       atomic {
  377.         gpCurrentParent = NULL;
  378.         gbCurrentHopCount = ROUTE_INVALID;
  379.         gbCurrentCost = ROUTE_INVALID;
  380.       }
  381.     }
  382.   }
  383.   uint8_t last_entry_sent;
  384.   task void SendRouteTask() {
  385.     TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *) &routeMsg.data[0];
  386.     RoutePacket *pRP = (RoutePacket *)&pMHMsg->data[0];
  387.     uint8_t length = offsetof(TOS_MHopMsg,data) + offsetof(RoutePacket,estList);
  388.     uint8_t maxEstEntries;
  389.     uint8_t i,j;
  390.     uint8_t last_index_added = 0;
  391.     if (gfSendRouteBusy) {
  392.       return;
  393.     }
  394.     dbg(DBG_ROUTE,"MultiHopWMEWMA Sending route update msg.n");
  395.     dbg(DBG_ROUTE,"Current cost: %d.n", gbCurrentCost);
  396.     maxEstEntries = TOSH_DATA_LENGTH - length;
  397.     maxEstEntries = maxEstEntries / sizeof(RPEstEntry);
  398.     pRP->parent = (gpCurrentParent) ? gpCurrentParent->id : ROUTE_INVALID;
  399.     pRP->cost = gbCurrentCost; 
  400.     for (i = 0,j = 0;i < ROUTE_TABLE_SIZE && j < maxEstEntries; i++) {
  401.       uint8_t table_index = i + last_entry_sent + 1;
  402.       if(table_index >= ROUTE_TABLE_SIZE) table_index -=ROUTE_TABLE_SIZE;
  403.       if (NeighborTbl[table_index].flags & NBRFLAG_VALID && NeighborTbl[table_index].receiveEst > 100) {
  404.         pRP->estList[j].id = NeighborTbl[table_index].id;
  405.         pRP->estList[j].receiveEst = NeighborTbl[table_index].receiveEst;
  406. j ++;
  407.         length += sizeof(RPEstEntry);
  408. last_index_added = table_index;
  409.         dbg(DBG_ROUTE,"Adding %d to route msg.n", pRP->estList[j].id);
  410.       }
  411.     }
  412.     last_entry_sent = last_index_added;
  413.     dbg(DBG_ROUTE,"Added total of %d entries to route msg.n", j);
  414.     pRP->estEntries = j;
  415.     pMHMsg->sourceaddr = pMHMsg->originaddr = TOS_LOCAL_ADDRESS;
  416.     pMHMsg->hopcount = gbCurrentHopCount;
  417.     pMHMsg->seqno = gCurrentSeqNo++;
  418.     if (call SendMsg.send(TOS_BCAST_ADDR, length, &routeMsg) == SUCCESS) {
  419.       gfSendRouteBusy = TRUE;
  420.     }
  421.   }
  422. #ifdef MULTI_HOP_DEBUG
  423.   task void SendDebugTask() {
  424.     struct SortDbgEntry sortTbl[ROUTE_TABLE_SIZE];
  425.     uint16_t max_length;
  426.     uint8_t length = offsetof(DebugPacket,estList);
  427.     DebugPacket *pRP = (DebugPacket *)call DebugSendMsg.getBuffer(&debugMsg,&max_length);
  428.     uint8_t maxEstEntries;
  429.     uint16_t parent;
  430.     uint8_t i,j;
  431.     dbg(DBG_ROUTE,"MultiHopWMEWMA Sending route debug msg.n");
  432.     maxEstEntries = max_length / sizeof(DBGEstEntry);
  433.     maxEstEntries --;
  434.     parent = (gpCurrentParent) ? gpCurrentParent->id : ROUTE_INVALID;
  435.     for (i = 0,j = 0;i < ROUTE_TABLE_SIZE; i++) {
  436.       if (NeighborTbl[i].flags & NBRFLAG_VALID && NeighborTbl[i].id != parent) {
  437.         sortTbl[j].id = NeighborTbl[i].id;
  438.         sortTbl[j].sendEst = NeighborTbl[i].sendEst;
  439.         sortTbl[j].hopcount = NeighborTbl[i].hop;
  440.         j++;
  441.       }
  442.     }
  443.     qsort (sortTbl,j,sizeof(struct SortDbgEntry),sortDebugEstFcn);
  444.     pRP->estEntries = (j > maxEstEntries) ? maxEstEntries : j;
  445.     pRP->estList[0].id = parent;
  446.     if(gpCurrentParent){
  447. pRP->estList[0].sendEst = gpCurrentParent->sendEst;
  448. pRP->estList[0].hopcount = gpCurrentParent->hop;
  449.     }
  450.     length += sizeof(DBGEstEntry);
  451.     for (i = 0; i < pRP->estEntries; i++) {
  452.       pRP->estList[i+1].id = sortTbl[i].id;
  453.       pRP->estList[i+1].sendEst = sortTbl[i].sendEst;
  454.       pRP->estList[i+1].hopcount = sortTbl[i].hopcount;
  455.       length += sizeof(DBGEstEntry);
  456.     }
  457.     pRP->estEntries ++;
  458.     call DebugSendMsg.send(&debugMsg, length);
  459.   }
  460.   int debugCounter;
  461. #endif
  462.   task void TimerTask() {
  463.     call Leds.redToggle();
  464.     dbg(DBG_ROUTE,"MultiHopWMEWMA timer task.n");
  465.     updateTable();
  466. #ifndef NDEBUG
  467.     {
  468.       int i;
  469.       dbg(DBG_ROUTE,"taddrtprnttcosttmisdtrcvdtlstSthoptrEsttsEsttDescn");
  470.       for (i = 0;i < ROUTE_TABLE_SIZE;i++) {
  471.         if (NeighborTbl[i].flags) {
  472.           dbg(DBG_ROUTE,"t%dt%dt%dt%dt%dt%dt%dt%dt%dt%dn",
  473.               NeighborTbl[i].id,
  474.               NeighborTbl[i].parent,
  475.               NeighborTbl[i].cost,
  476.               NeighborTbl[i].missed,
  477.               NeighborTbl[i].received,
  478.               NeighborTbl[i].lastSeqno,
  479.               NeighborTbl[i].hop,
  480.               NeighborTbl[i].receiveEst,
  481.               NeighborTbl[i].sendEst,
  482.               NeighborTbl[i].childLiveliness);
  483.         }
  484.       }
  485.       if (gpCurrentParent) {
  486.         dbg(DBG_ROUTE,"MultiHopWMEWMA: Parent = %dn",gpCurrentParent->id);
  487.       }
  488.     }
  489. #endif
  490.     chooseParent();
  491. #ifdef MULTI_HOP_DEBUG
  492.     if(TOS_LOCAL_ADDRESS != BASE_STATION_ADDRESS) debugCounter ++;
  493.     if(debugCounter > 1){
  494. post SendDebugTask();
  495. debugCounter = 0;
  496.     }else{
  497. #endif //MULTI_HOP_DEBUG
  498.       call ATimer.start(TIMER_ONE_SHOT, 32);
  499.       //post SendRouteTask();
  500. #ifdef MULTI_HOP_DEBUG
  501.     }
  502. #endif //MULTI_HOP_DEBUG
  503.   }
  504.   event result_t ATimer.fired(){
  505.     post SendRouteTask();
  506.     return SUCCESS;
  507.   }
  508.   command result_t StdControl.init() {
  509.     memset((void *)NeighborTbl,0,(sizeof(TableEntry) * ROUTE_TABLE_SIZE));
  510.     BaseStation.id = TOS_UART_ADDR;
  511.     BaseStation.parent = TOS_UART_ADDR;
  512.     BaseStation.flags = NBRFLAG_VALID;
  513.     BaseStation.hop = 0;
  514.     gpCurrentParent = NULL;
  515.     gbCurrentHopCount = ROUTE_INVALID;
  516.     gCurrentSeqNo = 0;
  517.     gwEstTicks = 0;
  518.     gUpdateInterval = DATA_TO_ROUTE_RATIO * DATA_FREQ;
  519.     gfSendRouteBusy = FALSE;
  520.     gSelfTimer = TRUE;
  521.     return SUCCESS;
  522.   }
  523.   command result_t StdControl.start() {
  524.     if (TOS_LOCAL_ADDRESS == BASE_STATION_ADDRESS) {
  525.       gpCurrentParent = &BaseStation;
  526.       gbCurrentHopCount = 0;
  527.       gbCurrentCost = 0;
  528.     }
  529.     if (gSelfTimer){
  530.       post TimerTask();
  531.       call Timer.start(TIMER_REPEAT,gUpdateInterval);
  532. #ifdef USE_WATCHDOG
  533.   call PoochHandler.start();
  534.   call WDT.start(gUpdateInterval * 5);
  535. #endif
  536.     }
  537.     //  post TimerTask();
  538.     //  call Timer.start(TIMER_REPEAT,gUpdateInterval);
  539.     //}
  540.     //call Leds.redToggle();
  541.     return SUCCESS;
  542.   }
  543.   command result_t StdControl.stop() {
  544.     call Timer.stop();
  545.     return SUCCESS;
  546.   }
  547.   command bool RouteSelect.isActive() {
  548. #if 0
  549.     bool Result = FALSE;
  550.     if (gpCurrentParent != NULL) {
  551.       Result = TRUE;
  552.     }
  553.     return Result;
  554. #endif
  555.     return TRUE;
  556.   }
  557.   void updateDescendant(uint16_t id){
  558. uint8_t indes = findEntry(id);
  559. if (indes == (uint8_t) ROUTE_INVALID) { return;}
  560. else{
  561. NeighborTbl[indes].childLiveliness = MAX_DESCENDANT_LIVE;
  562. }
  563.   }
  564.   command result_t RouteSelect.selectRoute(TOS_MsgPtr Msg, uint8_t id) {
  565.     TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
  566.     uint8_t iNbr;
  567.     bool fIsDuplicate;
  568.     result_t Result = SUCCESS;
  569.     if (gpCurrentParent == NULL) {
  570.       // If the msg is locally generated, then send it to the broadcast address
  571.       // This is necessary to seed the network.
  572.       if ((pMHMsg->sourceaddr == TOS_LOCAL_ADDRESS) &&
  573.           (pMHMsg->originaddr == TOS_LOCAL_ADDRESS)) {
  574.         pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
  575.         pMHMsg->hopcount = gbCurrentHopCount;
  576.         pMHMsg->seqno = gCurrentSeqNo++;
  577.         Msg->addr = TOS_BCAST_ADDR;
  578.         return SUCCESS;
  579.       }
  580.       else {
  581.         return FAIL;
  582.       }
  583.     }
  584.     if (gbCurrentHopCount >= pMHMsg->hopcount) {
  585.       // Possible cycle??
  586.       return FAIL;
  587.     }
  588.     
  589.     if ((pMHMsg->sourceaddr == TOS_LOCAL_ADDRESS) &&
  590.         (pMHMsg->originaddr == TOS_LOCAL_ADDRESS)) {
  591.       fIsDuplicate = FALSE;
  592.     }
  593.     else {
  594.       fIsDuplicate = updateNbrCounters(pMHMsg->sourceaddr,pMHMsg->seqno,&iNbr);
  595.     }
  596.     if (!fIsDuplicate) {
  597.       pMHMsg->sourceaddr = TOS_LOCAL_ADDRESS;
  598.       pMHMsg->hopcount = gbCurrentHopCount;
  599.       if (gpCurrentParent->id != TOS_UART_ADDR) {
  600.         pMHMsg->seqno = gCurrentSeqNo++;
  601.       }
  602.       Msg->addr = gpCurrentParent->id;
  603.       if(pMHMsg->originaddr != TOS_LOCAL_ADDRESS){
  604.   updateDescendant(pMHMsg->originaddr);
  605.       }
  606.     }
  607.     else {
  608.       Result = FAIL;
  609.     }
  610.     dbg(DBG_ROUTE,"MultiHopWMEWMA: Sequence Number: %dn", pMHMsg->seqno);
  611.     return Result;
  612.   }
  613.   command result_t RouteSelect.initializeFields(TOS_MsgPtr Msg, uint8_t id) {
  614.     TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
  615.     pMHMsg->sourceaddr = pMHMsg->originaddr = TOS_LOCAL_ADDRESS;
  616.     pMHMsg->hopcount = ROUTE_INVALID;
  617.     return SUCCESS;
  618.   }
  619.   command uint8_t* RouteSelect.getBuffer(TOS_MsgPtr Msg, uint16_t* Len) {
  620.   }
  621.   command uint16_t RouteControl.getParent() {
  622.     uint16_t addr;
  623.     addr = (gpCurrentParent != NULL) ? gpCurrentParent->id : 0xffff;
  624.     return addr;
  625.   }
  626.   command uint8_t RouteControl.getQuality() {
  627.     uint8_t val;
  628.     val = (gpCurrentParent != NULL) ? gpCurrentParent->sendEst : 0x00;
  629.     return val;
  630.   }
  631.   command uint8_t RouteControl.getDepth() {
  632.     return gbCurrentHopCount;
  633.   }
  634.   command uint8_t RouteControl.getOccupancy() {
  635.     return 0;
  636.   }
  637.   command uint16_t RouteControl.getSender(TOS_MsgPtr msg) {
  638.     TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)msg->data;
  639.     return pMHMsg->sourceaddr;
  640.   }
  641.   command result_t RouteControl.setUpdateInterval(uint16_t Interval) {
  642.     result_t Result;
  643.     call Timer.stop();
  644.     gUpdateInterval = (Interval * 1024L);  // * 1024 to make the math simpler
  645. gSelfTimer = TRUE;
  646.     Result = call Timer.start(TIMER_REPEAT,gUpdateInterval);
  647. #ifdef USE_WATCHDOG
  648. call PoochHandler.stop();
  649. call PoochHandler.start();
  650. call WDT.start(gUpdateInterval * 5);
  651. #endif
  652.     return Result;
  653.   }
  654.   command result_t RouteControl.manualUpdate() {
  655.     result_t Result;
  656.     
  657.     gSelfTimer = FALSE;
  658.     call Timer.stop();
  659.     Result = post TimerTask();
  660.     return Result;
  661.   }
  662.   event result_t Timer.fired() {
  663.     post TimerTask();
  664.     return SUCCESS;
  665.   }
  666.   event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr Msg) {
  667.     TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
  668.     RoutePacket *pRP = (RoutePacket *)&pMHMsg->data[0];
  669.     uint16_t saddr;
  670.     uint8_t i, iNbr;
  671.     call Leds.yellowToggle();
  672. #ifdef USE_WATCHDOG
  673. call WDT.reset();
  674. #endif
  675.     saddr = pMHMsg->sourceaddr;
  676.     updateNbrCounters(saddr,pMHMsg->seqno,&iNbr);
  677.     //    iNbr = findPreparedIndex(saddr);
  678.     NeighborTbl[iNbr].parent = pRP->parent;
  679.     NeighborTbl[iNbr].hop = pMHMsg->hopcount;
  680.     NeighborTbl[iNbr].cost = pRP->cost;
  681.     // If it is no longer my child, clear it
  682.     if (NeighborTbl[iNbr].childLiveliness > 0 && pRP->parent != TOS_LOCAL_ADDRESS)
  683.       NeighborTbl[iNbr].childLiveliness = 0;
  684.     // find out my address, extract the estimation
  685.     for (i = 0; i < pRP->estEntries; i++) {
  686.       if (pRP->estList[i].id == TOS_LOCAL_ADDRESS) {
  687.         NeighborTbl[iNbr].sendEst = pRP->estList[i].receiveEst;
  688.         NeighborTbl[iNbr].liveliness = LIVELINESS;
  689.       }
  690.     }
  691.     return Msg;
  692.   }
  693.   
  694.   event result_t Snoop.intercept[uint8_t id](TOS_MsgPtr Msg, void *Payload, uint16_t Len) {
  695.     TOS_MHopMsg *pMHMsg = (TOS_MHopMsg *)&Msg->data[0];
  696.     uint8_t iNbr;
  697.     updateNbrCounters(pMHMsg->sourceaddr,pMHMsg->seqno,&iNbr);
  698.     
  699.     // Extract routing information if we know this is a multihop message
  700.     // Something in the future.
  701.     return SUCCESS;
  702.   }
  703.   event result_t SendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
  704.     gfSendRouteBusy = FALSE;
  705.     return SUCCESS;
  706.   }
  707.   event result_t DebugSendMsg.sendDone(TOS_MsgPtr pMsg, result_t success) {
  708.     return SUCCESS;
  709.   }
  710. }