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

网络

开发平台:

Others

  1. includes crc;
  2. includes CC1000Const;
  3. includes zmacInfo;
  4. includes DrandInfo;
  5. module CC1000RadioIntM {
  6.   provides {
  7.     interface StdControl;
  8.     interface BareSendMsg as Send;
  9.     interface ReceiveMsg as Receive;
  10.     interface RadioCoordinator as RadioSendCoordinator;
  11.     interface RadioCoordinator as RadioReceiveCoordinator;
  12.     interface MacControl;
  13.     interface MacBackoff;
  14.     interface LowPowerListening;
  15.     interface SetDrand;
  16.     
  17.     // legacy commands supported, but should now use the
  18.     // Low Power Listening interface
  19.     async command result_t SetListeningMode(uint8_t power);
  20.     async command uint8_t GetListeningMode();
  21.     async command result_t SetTransmitMode(uint8_t power);
  22.     async command uint8_t GetTransmitMode();
  23.     // Used for debugging the noise floor (gets the current squelch value)
  24.     async command uint16_t GetSquelch();
  25.     // Used for debugging; gets an estimate of the power consumed by the radio
  26.     async command uint16_t GetPower();
  27.     async command uint16_t GetDataSent();
  28.     async command uint16_t GetPower_tx();
  29.     async command uint16_t GetPower_rx();
  30.     async command uint16_t GetPower_sp();
  31.     async command result_t ResetPower();
  32.     async command result_t ResetDataSent();
  33.   }
  34.   uses {
  35.     interface SClock;
  36.     interface StdControl as SubControl;
  37.     interface PowerManagement;
  38.     interface StdControl as CC1000StdControl;
  39.     interface CC1000Control;
  40.     interface Random;
  41.     interface ADCControl;
  42.     interface ADC as RSSIADC;
  43.     interface SpiByteFifo;
  44.     interface StdControl as TimerControl;
  45.     interface Timer as WakeupTimer;
  46.     interface Timer as SquelchTimer;
  47.     interface Timer as TDMATimer;
  48.     interface Leds;
  49.   }
  50. }
  51. implementation {
  52. #include "DrandMSG.h"
  53. #include "zmacConst.h"
  54. #ifdef ZMAC_DEBUG
  55. #include "SODebug.h"
  56. #endif
  57.   enum {
  58.     NULL_STATE,
  59.     TX_STATE,
  60.     DISABLED_STATE,
  61.     IDLE_STATE,
  62.     PRETX_STATE,
  63.     SYNC_STATE,
  64.     RX_STATE,
  65.     SENDING_ACK,
  66.     POWER_DOWN_STATE,
  67.     PULSE_CHECK_STATE,
  68.   };
  69.   enum {
  70.     TXSTATE_WAIT,
  71.     TXSTATE_START,
  72.     TXSTATE_PREAMBLE,
  73.     TXSTATE_SYNC,
  74.     TXSTATE_DATA,
  75.     TXSTATE_CRC,
  76.     TXSTATE_FLUSH,
  77.     TXSTATE_WAIT_FOR_ACK,
  78.     TXSTATE_READ_ACK,
  79.     TXSTATE_DONE
  80.   };
  81.   enum {
  82.     SYNC_BYTE = 0x33,
  83.     NSYNC_BYTE = 0xcc,
  84.     SYNC_WORD = 0x33cc,
  85.     NSYNC_WORD = 0xcc33,
  86.     ACK_LENGTH = 16,
  87.     MAX_ACK_WAIT = 18,
  88.     TIME_BETWEEN_CHECKS = 50,
  89.     TIME_AFTER_CHECK = 30,
  90.     CHECK_MA_COUNT = 100, //8888,
  91.     SEND_MA_COUNT = 100, //7200,
  92.     PREAMBLE_LENGTH_TO_BASE = 8,
  93.     RECEIVE_MA_COUNT = 100, //9600
  94.   };
  95.   uint8_t ack_code[5] = {0xab, 0xba, 0x83, 0xaa, 0xaa};
  96.   uint8_t RadioState;
  97.   uint8_t RadioTxState;
  98.   norace uint8_t iRSSIcount;
  99.   uint8_t RSSIInitState;
  100.   uint8_t iSquelchCount;
  101.   uint16_t txlength;
  102.   uint16_t rxlength;
  103.   TOS_MsgPtr txbufptr;  // pointer to transmit buffer
  104.   TOS_MsgPtr rxbufptr;  // pointer to receive buffer
  105.   TOS_Msg retxbuf; //re-transmit buffer in case ECN preempts send 
  106.   TOS_Msg RxBuf; // save received messages
  107.   uint8_t NextTxByte;
  108.   uint8_t lplpower;        //  low power listening mode
  109.   uint8_t lplpowertx;      //  low power listening transmit mode
  110.   uint16_t preamblelen;    //  current length of the preamble
  111.   uint16_t sleeptime;       //  current check interval (sleep time)
  112.  
  113.   uint16_t PreambleCount;   //  found a valid preamble
  114.   uint8_t SOFCount;
  115.   uint16_t search_word;
  116.   //modified by Mahesh
  117.   enum {
  118.     BMAC,
  119.     ZMAC
  120.   };
  121.   enum{
  122.     MAX_VAL = 0xFFFF
  123.   };
  124.   enum{
  125.     POSITIVE = 1,
  126.     NEGATIVE = 2,
  127.     ZERO = 3
  128.   };
  129.   
  130.   //  nodeInfo *nbrInfo;
  131.   nodeInfo nbrInfo[MAX_NBR], myInfo; //CHANGE THIS, ONLY FOR TESTING !!!!!!!
  132.   GTime currentDiff, constOffset;
  133.   uint16_t currentSender;
  134.   uint8_t currentSign;
  135.   uint8_t currentMAC; // default must be BMAC and change to ZMAC after DRAND completes
  136.   uint16_t localFrameLength; // local frame length in slots
  137.   uint16_t globalFrameLength;
  138.   uint16_t slotSize; 
  139.   uint16_t nextHop;
  140.   uint16_t ownSlot;
  141.   uint16_t slots_since_ecnsend;
  142.   uint16_t slots_since_ecnrecv;
  143.   uint16_t slots_since_ecncheck;
  144.   uint16_t globalFrameSize;
  145.   uint16_t localFrameSize;
  146.   uint16_t globalSlot;
  147.   uint16_t currentSlot;
  148.   uint16_t slotMultiplier;
  149.   uint32_t slotNum;
  150.   uint16_t packetsSent;
  151.   uint16_t pktsLastSync;
  152.   bool needTimeSync;
  153.   uint16_t congBackOffs;
  154.   double avgLoss;
  155.   uint32_t curHCLlist;
  156.   bool HCLselect;
  157.   bool ackOrig;
  158.   bool ecnPending;
  159.   bool ecnforward;
  160.   bool enableHCL;
  161.   bool pureHCL;
  162.   TOS_Msg ecnMsgHdr;
  163.   TOS_Msg ecnForwardMsgHdr;
  164.   TOS_Msg syncMsgHdr;
  165.   union {
  166.     uint16_t W;
  167.     struct {
  168.       uint8_t LSB;
  169.       uint8_t MSB;
  170.     };
  171.   } RxShiftBuf;
  172.   uint8_t RxBitOffset; // bit offset for spibus
  173.   uint16_t RxByteCnt; // received byte counter
  174.   uint16_t TxByteCnt;
  175.   uint16_t RSSISampleFreq; // in Bytes rcvd per sample
  176.   norace bool bInvertRxData; // data inverted
  177.   norace bool bTxPending;
  178.   bool bAckEnable;
  179.   bool bCCAEnable;
  180.   bool bTxBusy;
  181.   bool bRSSIValid;
  182.   uint16_t CC1K_PulseLevel;
  183.   uint16_t usRunningCRC; // Running CRC variable
  184.   uint16_t usRSSIVal;
  185.   uint16_t usSquelchVal;
  186.   uint16_t usTempSquelch;
  187.   uint8_t usSquelchIndex;
  188.   norace uint8_t pulse_check_count;
  189.   norace uint16_t pulse_check_sum;
  190.   norace uint16_t send_sum;
  191.   norace uint16_t receive_sum;
  192.   norace uint16_t power_sum;
  193.   norace uint16_t sp_sum;
  194.   norace uint16_t rx_sum;
  195.   norace uint16_t tx_sum;
  196.   norace uint16_t dataSent;
  197.   uint16_t usSquelchTable[CC1K_SquelchTableSize];
  198.   int16_t sMacDelay;    // MAC delay for the next transmission
  199.   // XXX-PB:
  200.   // Here's the deal, the mica (RFM) radio stacks used TOS_LOCAL_ADDRESS
  201.   // to determine if an L2 ack was reqd.  This stack doesn't do L2 acks
  202.   // and, thus doesn't need it.  HOWEVER, some set-mote-id versions
  203.   // break if this symbol is missing from the binary.
  204.   // Thus, I put this LocalAddr here and set it to TOS_LOCAL_ADDRESS
  205.   // to keep things happy for now.
  206.   volatile uint16_t LocalAddr;
  207.   ///**********************************************************
  208.   //* local function definitions
  209.   //**********************************************************/
  210.   /*
  211.     int sortByShort(const void *x, const void *y) {
  212.     uint16_t* x1 = (uint16_t*)x;
  213.     uint16_t* y1 = (uint16_t*)y;
  214.     if (x1[0] > y1[0]) return -1;
  215.     if (x1[0] == y1[0]) return 0;
  216.     if (x1[0] < y1[0]) return 1;
  217.     return 0; // shouldn't reach here becasue it covers all the cases
  218.     }
  219.   */
  220.   uint16_t getOwnerBackoff(){
  221.     return (call Random.rand() & (T_O - 1)) + 1;
  222.   }
  223.   uint16_t getNonOwnerBackoff(){
  224.     return (call Random.rand() & (T_NO - 1)) + T_O + 1;
  225.   }
  226.   void DivTime2(GTime* B, GTime* A){
  227.     if (A->mticks % 2 == 1){
  228.       B->mticks = (A->mticks >> 1);
  229.       B->sticks = (A->sticks >> 1)  + ((MAX_VAL) >>1);
  230.     }
  231.     else{
  232.       B->mticks = (A->mticks >>1);
  233.       B->sticks = (A->sticks >>1);
  234.     }
  235.   }
  236.   void AddTime(GTime* C, GTime* A, GTime* B){
  237.     if ((MAX_VAL - B->sticks) < A->sticks){
  238.       C->sticks = A->sticks - (MAX_VAL - B->sticks);
  239.       C->mticks = A->mticks + B->mticks + 1;
  240.     }
  241.     else{
  242.       C->sticks = A->sticks + B->sticks;
  243.       C->mticks = A->mticks + B->mticks;
  244.     }
  245.   }
  246.   void SubTime(GTime* C, GTime* A, GTime* B){
  247.     if (B->sticks > A->sticks){
  248.       C->sticks = MAX_VAL - (B->sticks - A->sticks);
  249.       C->mticks = A->mticks - (B->mticks + 1);
  250.     }
  251.     else {
  252.       C->sticks = A->sticks -  B->sticks;
  253.       C->mticks = A->mticks -  B->mticks;
  254.     }
  255.   }
  256.   uint16_t getZMACBackoff(uint16_t residualBackoff){
  257.     if(residualBackoff > 0){
  258.       congBackOffs++;
  259.       if((currentSlot == ownSlot) && (residualBackoff >= T_O)){
  260.         return getOwnerBackoff();
  261.       } else if((currentSlot != ownSlot) && (residualBackoff < T_O)){
  262.         if((residualBackoff + T_O) < (T_O + T_NO))
  263.           return (residualBackoff + T_O);
  264.         else
  265.           return getNonOwnerBackoff();
  266.       } else
  267.         return residualBackoff;
  268.     } else{
  269.       if(currentSlot == ownSlot)
  270.         return getOwnerBackoff();
  271.       else
  272.         return getNonOwnerBackoff();
  273.     }
  274.   }
  275.   uint8_t ModSubTime(GTime* C, GTime* A, GTime* B){
  276.     uint8_t retval;
  277.     if (A->mticks > B->mticks) 
  278.       retval = POSITIVE;
  279.     else if (A->mticks < B->mticks) 
  280.       retval = NEGATIVE;
  281.     else{
  282.       if (A->sticks > B->sticks)
  283.         retval = POSITIVE;
  284.       else if (A->sticks < B->sticks)
  285.         retval = NEGATIVE;
  286.       else
  287.         retval = ZERO;
  288.     }
  289.     if (retval == POSITIVE) SubTime(C,A,B);
  290.     else if (retval == NEGATIVE) SubTime(C,B,A);
  291.     else {
  292.       C->sticks = 0;
  293.       C->mticks = 0;
  294.     }
  295.     return retval;
  296.   }
  297.   bool IsHCL(uint32_t gSlot){
  298.     uint32_t tempHCL = 0x1;
  299.     bool flag;
  300.     tempHCL = tempHCL << gSlot;
  301.     atomic{
  302.       if(tempHCL & curHCLlist)
  303.         flag = TRUE;
  304.       else
  305.         flag = FALSE;
  306.     }
  307.     return flag;
  308.   }
  309.   task void adjustSquelch() {
  310.     uint16_t tempArray[CC1K_SquelchTableSize];
  311.     char i,j,min; 
  312.     uint16_t min_value;
  313.     uint32_t tempsquelch;
  314.     atomic {
  315.       usSquelchTable[usSquelchIndex] = usTempSquelch;
  316.       usSquelchIndex++;
  317.       if (usSquelchIndex >= CC1K_SquelchTableSize)
  318.         usSquelchIndex = 0;
  319.       if (iSquelchCount <= CC1K_SquelchCount)
  320.         iSquelchCount++;  
  321.     }
  322.     for (i=0; i<CC1K_SquelchTableSize; i++) {
  323.       tempArray[(int)i] = usSquelchTable[(int)i];
  324.     }
  325.     min = 0;
  326.     //    for (j = 0; j < ((CC1K_SquelchTableSize) >> 1); j++) {
  327.     for (j = 0; j < 3; j++) {
  328.       for (i = 1; i < CC1K_SquelchTableSize; i++) {
  329.         if ((tempArray[(int)i] != 0xFFFF) && 
  330.             ((tempArray[(int)i] > tempArray[(int)min]) ||
  331.              (tempArray[(int)min] == 0xFFFF))) {
  332.           min = i;
  333.         }
  334.       }
  335.       min_value = tempArray[(int)min];
  336.       tempArray[(int)min] = 0xFFFF;
  337.     }
  338.     tempsquelch = ((uint32_t)(usSquelchVal << 5) + (uint32_t)(min_value << 1));
  339.     atomic usSquelchVal = (uint16_t)((tempsquelch / 34) & 0x0FFFF);
  340.     /*
  341.     // XXX: qsort actually causes ~600bits/sec lower bandwidth... why???
  342.     //
  343.     qsort (tempArray,CC1K_SquelchTableSize, sizeof(uint16_t),sortByShort);
  344.     min_value = tempArray[CC1K_SquelchTableSize >> 1];
  345.     atomic usSquelchVal = ((usSquelchVal << 5) + (min_value << 1)) / 34;
  346.     */
  347.   }
  348.   void getTimeDiff(){ // called as soon as time sync message is received, regardless of crc
  349.     atomic{
  350.       uint16_t i, trust;
  351.       GTime loctime, timeStamp;
  352.       syncMsgType* syncMsgPtr = (syncMsgType *) rxbufptr->data;
  353.       timeStamp.mticks = syncMsgPtr->mticks;
  354.       timeStamp.sticks = syncMsgPtr->sticks;
  355.       trust = syncMsgPtr->trust;
  356.       currentSender = syncMsgPtr->sender;
  357.       call SClock.getTime(&loctime);
  358.       currentSign = ModSubTime(&currentDiff, &timeStamp, &loctime);
  359.       if(trust < MIN_TRUST)
  360.         trust = MIN_TRUST;
  361.       if(trust < MAX_TRUST){
  362.         for(i = 0; i < trust; i++){
  363.           DivTime2(&currentDiff, &currentDiff);
  364.         }
  365.       }
  366.     }
  367.   }
  368.   void Blacklist(uint8_t slot, uint8_t fsize){
  369.     uint8_t black_slot;
  370.     atomic {
  371.       if(fsize <= globalFrameLength){
  372.         black_slot = slot;
  373.         while(black_slot < globalFrameLength){
  374.           uint32_t tempHCL2 = 0x1;
  375.           tempHCL2 = tempHCL2 << black_slot;
  376.           curHCLlist = curHCLlist | tempHCL2;
  377.           black_slot = black_slot + fsize;
  378.         }
  379.       }
  380.     }
  381.   }
  382.   
  383.   task void adjustTime(){
  384.     needTimeSync = TRUE;
  385.     call SClock.setTime(currentSign, &currentDiff);
  386. #ifdef ZMAC_TIME_SYNC
  387.     SODbg(DBG_USR2, "diff = %u, %u, from %un", currentDiff.mticks, currentDiff.sticks, currentSender);
  388. #endif
  389.   }
  390.   task void PacketRcvd(){
  391.     TOS_MsgPtr pBuf;
  392.     ecnForwardMsgType *recvEcnMsgPtr;
  393.     ecnForwardMsgType *ecnForwardMsgPtr;
  394.     atomic {
  395.       if(pktsLastSync > SYNC_PERIOD){
  396.         atomic{ 
  397.           ackOrig = bAckEnable;
  398.           bAckEnable = FALSE;
  399.         }
  400.         call Send.send(&syncMsgHdr);
  401.         pktsLastSync = 0;
  402.       }
  403.       pktsLastSync++;
  404.       rxbufptr->time = 0;
  405.       pBuf = rxbufptr;
  406.       recvEcnMsgPtr = (ecnForwardMsgType *) rxbufptr->data;
  407.       ecnForwardMsgPtr = (ecnForwardMsgType *) ecnForwardMsgHdr.data;
  408. #ifdef ZMAC_ECN
  409.       if((currentMAC == ZMAC) && (pBuf->type == ECNTYPE)){
  410.         SODbg(DBG_USR2,"Received %u hop ECN from %u, deciding whether significant..n",
  411.               recvEcnMsgPtr->hopCount, recvEcnMsgPtr->senderAddress);
  412.       }
  413. #endif
  414.       if((currentMAC == ZMAC) && (HCLselect) && (pBuf->type == ECNTYPE) && (pBuf->crc != 0) &&
  415.          (recvEcnMsgPtr->senderAddress != TOS_LOCAL_ADDRESS)){ //Message is an ECN
  416.         if((recvEcnMsgPtr->hopCount == 0) && (recvEcnMsgPtr->nextHop == TOS_LOCAL_ADDRESS)){
  417. #ifdef ZMAC_ECN
  418.           SODbg(DBG_USR2,"Received one-hop ECN from %un", recvEcnMsgPtr->senderAddress);
  419. #endif
  420.           ecnForwardMsgPtr->hopCount = 1;
  421.           ecnForwardMsgPtr->nextHop = nextHop;
  422.           ecnForwardMsgPtr->senderAddress = TOS_LOCAL_ADDRESS;
  423.           if(!bTxBusy){
  424.             ackOrig = bAckEnable;
  425.             bAckEnable = FALSE;
  426.             call Send.send(&ecnForwardMsgHdr);  //take care of case where we are not currently sending
  427. #ifdef ZMAC_ECN
  428.             SODbg(DBG_USR2,"Forwarded ECNn");
  429. #endif
  430.           } else
  431.             ecnforward = TRUE;
  432.         } else if(recvEcnMsgPtr->hopCount == 1){ //check if two-hop ECN
  433. #ifdef ZMAC_ECN
  434.           SODbg(DBG_USR2,"????????????????????? Received two hop ECN from %un", recvEcnMsgPtr->senderAddress);
  435. #endif
  436.           atomic enableHCL = TRUE;
  437.           SODbg(DBG_USR2,"Going into ECNn");
  438.           if(recvEcnMsgPtr->senderAddress == nextHop){  //check forwarding node's address
  439.             //suppress ECN
  440. #ifdef ZMAC_ECN
  441.             SODbg(DBG_USR2,"Suppressed own ECNn");
  442. #endif
  443.             atomic ecnPending = FALSE;
  444.             slots_since_ecnsend = 0;
  445.             slots_since_ecnrecv = 0;
  446.           }
  447.         }
  448.       } else if((pBuf->type != SYNCTYPE) && (pBuf->type != ECNTYPE)){
  449. #ifdef ZMAC_ECN
  450.         //        SODbg(DBG_USR2,"Received packet of type %u, crc = %un", pBuf->type, pBuf->crc);
  451. #endif
  452.         pBuf = signal Receive.receive((TOS_MsgPtr)pBuf);
  453.       }
  454.       
  455.       if (pBuf)
  456.         rxbufptr = pBuf;
  457.       rxbufptr->length = 0;
  458.     }
  459.     call SpiByteFifo.enableIntr();
  460.   }
  461.   
  462.   task void PacketSent() {
  463.     TOS_MsgPtr pBuf; //store buf on stack 
  464.     atomic {
  465.       txbufptr->time = 0;
  466.       pBuf = txbufptr;
  467.     }
  468.       
  469.     if ((txbufptr->type != ECNTYPE) && (txbufptr->type != SYNCTYPE)){
  470.       if(txbufptr->type == AM_MULTIHOP)
  471.         dataSent++;
  472.       signal Send.sendDone((TOS_MsgPtr)pBuf, SUCCESS);
  473.     } else if(txbufptr->type == SYNCTYPE){
  474. #ifdef ZMAC_DEBUG
  475.       //      SODbg(DBG_USR2, "Sent one sync message $$$$$$$$$n");
  476. #endif
  477.     } else if(txbufptr->type == ECNTYPE){
  478. #ifdef ZMAC_DEBUG
  479.       //      SODbg(DBG_USR2, "Sent one ecn message $$$$$$$$$n");
  480. #endif
  481.     }
  482.       
  483.     atomic bTxBusy = FALSE;
  484.     if(pktsLastSync > SYNC_PERIOD){
  485.       atomic{
  486.         ackOrig = bAckEnable;
  487.         bAckEnable = FALSE;
  488.       }
  489.       call Send.send(&syncMsgHdr);
  490.       pktsLastSync = 0;
  491.     } else if((currentMAC == ZMAC) && (ecnforward == TRUE)){
  492.       atomic{
  493.         ackOrig = bAckEnable;
  494.         bAckEnable = FALSE;
  495.       }
  496.       call Send.send(&ecnForwardMsgHdr);
  497.       atomic ecnforward = FALSE;
  498. #ifdef ZMAC_ECN
  499.       SODbg(DBG_USR2,"Forwarded ECNn");
  500. #endif
  501.     } else if((currentMAC == ZMAC) && (ecnPending == TRUE)){
  502.       atomic{
  503.         ackOrig = bAckEnable;
  504.         bAckEnable = FALSE;
  505.       }
  506.       call Send.send(&ecnMsgHdr);
  507.       atomic ecnPending = FALSE;
  508.       atomic slots_since_ecnsend = 0;
  509. #ifdef ZMAC_ECN
  510.       SODbg(DBG_USR2,"Sent own ECNn");
  511. #endif
  512.     }
  513.   }
  514.   ///**********************************************************
  515.   //* Exported interface functions
  516.   //**********************************************************/
  517.   command void SetDrand.setParent(uint8_t id){ nextHop = id; }
  518.   command result_t SetDrand.Set(nodeInfo *mInfo, uint8_t nHop, nodeInfo *nInfo, uint16_t sSize){
  519.     uint32_t slotOffset = 0, globalTimeStamp = 0;
  520.     GTime loctime;
  521.     uint8_t i = 0;
  522.     slotSize = sSize;
  523.     nextHop = nHop;
  524.     if(0){
  525.       /*       localFrameLength = myInfo->frame; */
  526.       /*       ownSlot = myInfo->slot; */
  527.       /*       nbrInfo = nInfo; */
  528.       /*       for(i = 0; (i < MAX_NBR) && (nbrInfo[i].nodeID != 0xFF); i++) */
  529.       /*         if(nbrInfo[i].bitMap & TWO_HOP) */
  530.       /*           Blacklist(nbrInfo[i].slot, nbrInfo[i].frame); */
  531.     } else{ // USE THIS ONLY FOR TESTING
  532.       for(i = 0 ; i<MAX_NBR ; i++){ // initialize the nbr table
  533.         nbrInfo[i].nodeID = 0xFF;
  534.         nbrInfo[i].slot = 0xFF;
  535.         nbrInfo[i].frame = 0xFF;
  536.         nbrInfo[i].bitMap = 0x0;
  537.       }
  538. #include "nbrTable.h"
  539.       /*       slotSize = sSize; */
  540.       /*       localFrameLength = 8; */
  541.       /*       nextHop = nHop; */
  542.       /*       switch(TOS_LOCAL_ADDRESS){ */
  543.       /*       case 1: */
  544.       /*         ownSlot = 6; */
  545.       /*         break; */
  546.       /*       case 10: */
  547.       /*         ownSlot = 4; */
  548.       /*         break; */
  549.       /*       case 11: */
  550.       /*         ownSlot = 0; */
  551.       /*         break; */
  552.       /*       case 13: */
  553.       /*         ownSlot = 1; */
  554.       /*         break; */
  555.       /*       case 2: */
  556.       /*         ownSlot = 1; */
  557.       /*         break; */
  558.       /*       case 20: */
  559.       /*         ownSlot = 1; */
  560.       /*         break; */
  561.       /*       case 21: */
  562.       /*         ownSlot = 2; */
  563.       /*         break; */
  564.       /*       case 22: */
  565.       /*         ownSlot = 7; */
  566.       /*         break; */
  567.       /*       case 24: */
  568.       /*         ownSlot = 0; */
  569.       /*         break; */
  570.       /*       case 0: */
  571.       /*         ownSlot = 5; */
  572.       /*         break; */
  573.       /*       case 8: */
  574.       /*         ownSlot = 2; */
  575.       /*         break; */
  576.       /*       case 9: */
  577.       /*         ownSlot = 3; */
  578.       /*         break; */
  579.       /*       } */
  580.     }
  581.     localFrameSize = localFrameLength * slotSize;
  582.     globalFrameSize = globalFrameLength * slotSize;
  583.     slotMultiplier = (uint16_t) (slotSize * 1.024);
  584.     call SClock.getTime(&loctime);
  585.     globalTimeStamp = (uint32_t)(loctime.mticks * 568.889 + loctime.sticks * 0.00868056); //in ms
  586.     slotOffset = (uint32_t) (1.024 * (slotSize - (globalTimeStamp % slotSize))); // in timer units .976562 = 1000/1024
  587.     slotNum = (uint32_t) (globalTimeStamp/slotSize);
  588.     currentSlot = slotNum & (localFrameLength - 1);
  589.     globalSlot = slotNum & (globalFrameLength - 1);
  590.     
  591.     call TDMATimer.start(TIMER_ONE_SHOT, slotOffset);
  592. #ifdef ZMAC_TIMER
  593.     // SODbg(DBG_USR2,"Started timer slotsize - offset is %in",slotSize - slotOffset);
  594. #endif
  595.     return SUCCESS; 
  596.   }
  597.   command result_t StdControl.init() {
  598.     char i;
  599.     ecnMsgType *ecnMsgPtr = (ecnMsgType *) ecnMsgHdr.data;
  600.     atomic {
  601.       RadioState = DISABLED_STATE;
  602.       RadioTxState = TXSTATE_PREAMBLE;
  603.       rxbufptr = &RxBuf;
  604.       rxbufptr->length = 0;
  605.       rxlength = MSG_DATA_SIZE-2;
  606.       RxBitOffset = 0;
  607.       iSquelchCount = 0;
  608.       
  609.       PreambleCount = 0;
  610.       RSSISampleFreq = 0;
  611.       RxShiftBuf.W = 0;
  612.       iRSSIcount = 0;
  613.       bTxPending = FALSE;
  614.       bTxBusy = FALSE;
  615.       bRSSIValid = FALSE;
  616.       bAckEnable = FALSE; // to test for ECN only
  617.       bCCAEnable = TRUE;
  618.       CC1K_PulseLevel = 300;
  619.       sMacDelay = -1;
  620.       usRSSIVal = -1;
  621.       usSquelchIndex = 0;
  622.       pulse_check_count = 0;
  623.       lplpower =  0;//0x87;
  624.       RSSIInitState = NULL_STATE;
  625.       //      if(TOS_LOCAL_ADDRESS == 0) lplpower = 0;
  626.       //      lplpowertx = 7;
  627.       usSquelchVal = CC1K_SquelchInit;
  628.       currentMAC = BMAC;
  629.       congBackOffs = 0;
  630.       packetsSent = 0;
  631.       pktsLastSync = 0;
  632.       avgLoss = 0.0;
  633.       curHCLlist = 0;
  634.       globalFrameLength = GLOBAL_FRAME_LENGTH;
  635.       localFrameLength = GLOBAL_FRAME_LENGTH;
  636.       slotSize = 50;
  637.       localFrameSize = localFrameLength * slotSize;
  638.       globalFrameSize = globalFrameLength * slotSize;
  639.       ackOrig = bAckEnable;
  640.       ecnPending = FALSE;
  641.       ecnforward = FALSE;
  642.       enableHCL = FALSE; // ecn flag, set if currently ecn is going on ...
  643.       pureHCL = FALSE;
  644.       HCLselect = SELECTHCL;
  645.       needTimeSync = FALSE;
  646.       slots_since_ecnsend = 0;
  647.       slots_since_ecnrecv = 0;
  648.       slots_since_ecncheck = 0;
  649.       ecnMsgHdr.type = ECNTYPE;  //set ecnMsg headers
  650.       ecnMsgHdr.addr = TOS_BCAST_ADDR; //ECN Indicator;
  651.       ecnMsgHdr.length = sizeof(ecnMsgType);
  652.       ecnMsgHdr.group = 125;
  653.       ecnMsgHdr.crc = 0;
  654.       ecnForwardMsgHdr.type = ECNTYPE;
  655.       ecnForwardMsgHdr.addr = TOS_BCAST_ADDR; 
  656.       ecnForwardMsgHdr.length = sizeof(ecnMsgType);
  657.       ecnForwardMsgHdr.group = 125;
  658.       ecnForwardMsgHdr.crc = 0;
  659.       syncMsgHdr.type = SYNCTYPE;  //set syncMsg headers
  660.       syncMsgHdr.addr = TOS_BCAST_ADDR; //SYNC Indicator;
  661.       syncMsgHdr.length = sizeof(syncMsgType);
  662.       syncMsgHdr.group = 125;
  663.       syncMsgHdr.crc = 0;
  664.       
  665.       ecnMsgPtr->hopCount = 0; //hopcount
  666.       ecnMsgPtr->nextHop = nextHop; //parent node
  667.       ecnMsgPtr->senderAddress = TOS_LOCAL_ADDRESS;
  668.     }
  669.     for (i = 0; i < CC1K_SquelchTableSize; i++)
  670.       usSquelchTable[(int)i] = CC1K_SquelchInit;
  671.     call SpiByteFifo.initSlave(); // set spi bus to slave mode
  672.    
  673.     call CC1000StdControl.init();
  674.     call CC1000Control.SelectLock(0x9); // Select MANCHESTER VIOLATION
  675.     bInvertRxData = call CC1000Control.GetLOStatus();
  676.     call ADCControl.bindPort(TOS_ADC_CC_RSSI_PORT,TOSH_ACTUAL_CC_RSSI_PORT);
  677.     call ADCControl.init();
  678.     
  679.     call Random.init();
  680.     call TimerControl.init();
  681. #ifdef ZMAC_DEBUG
  682.     init_debug();
  683. #endif
  684.     LocalAddr = TOS_LOCAL_ADDRESS;
  685.     return SUCCESS;
  686.   }
  687.   
  688.   /**
  689.    * Get the current Low Power Listening transmit mode
  690.    * @return mode number (see SetListeningMode)
  691.    */
  692.   async command uint8_t LowPowerListening.GetTransmitMode() {
  693.     return lplpowertx;
  694.   }
  695.   // legacy support
  696.   async command uint8_t GetTransmitMode() {
  697.     return call LowPowerListening.GetTransmitMode();
  698.   }
  699.   /**
  700.    * Set the transmit mode.  This allows for hybrid schemes where
  701.    * the transmit mode is different than the receive mode.
  702.    * Use SetListeningMode first, then change the mode with SetTransmitMode.
  703.    *
  704.    * @param mode mode number (see SetListeningMode)
  705.    * @return SUCCESS if the mode was successfully changed
  706.    */
  707.   async command result_t LowPowerListening.SetTransmitMode(uint8_t power) {
  708.     if ((power >= CC1K_LPL_STATES) || (power == lplpowertx))
  709.       return FAIL;
  710.     // check if the radio is currently doing something
  711.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  712.                           (RadioState == IDLE_STATE) ||
  713.                           (RadioState == DISABLED_STATE))) {
  714.       atomic {
  715.         lplpowertx = power;
  716.         preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8)
  717.                        | PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  718.       }
  719.       return SUCCESS;
  720.     }
  721.     return FAIL;
  722.   }
  723.   // legacy support
  724.   async command result_t SetTransmitMode(uint8_t power) {
  725.     return call LowPowerListening.SetTransmitMode(power);
  726.   }
  727.   /**
  728.    * Set the current Low Power Listening mode.
  729.    * Setting the LPL mode sets both the check interval and preamble length.
  730.    *
  731.    * Modes include:
  732.    *  0 = Radio full on
  733.    *  1 = 10ms check interval
  734.    *  2 = 25ms check interval
  735.    *  3 = 50ms check interval
  736.    *  4 = 100ms check interval (recommended)
  737.    *  5 = 200ms check interval
  738.    *  6 = 400ms check interval
  739.    *  7 = 800ms check interval
  740.    *  8 = 1600ms check interval
  741.    *
  742.    * @param mode the mode number
  743.    * @return SUCCESS if the mode was successfully changed
  744.    */
  745.   async command result_t LowPowerListening.SetListeningMode(uint8_t power) {
  746.     // valid low power listening values are 0 to 8
  747.     // 0 is "always on" and 8 is lowest duty cycle
  748.     if ((power >= CC1K_LPL_STATES) || (power == lplpower))
  749.       return FAIL;
  750.     // check if the radio is currently doing something
  751.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  752.                           (RadioState == IDLE_STATE) ||
  753.                           (RadioState == DISABLED_STATE))) {
  754.       // change receiving function in CC1000Radio
  755.       call WakeupTimer.stop();
  756.       atomic {
  757.         if (lplpower == lplpowertx) {
  758.           lplpowertx = power;
  759.         }
  760.         lplpower = power;
  761.       }
  762.       // if successful, change power here
  763.       if (RadioState == IDLE_STATE) {
  764.         RadioState = DISABLED_STATE;
  765.         call StdControl.stop();
  766.         call StdControl.start();
  767.       }
  768.       if (RadioState == POWER_DOWN_STATE) {
  769.         RadioState = DISABLED_STATE;
  770.         call StdControl.start();
  771.         call PowerManagement.adjustPower();
  772.       }
  773.     }
  774.     else {
  775.       return FAIL;
  776.     }
  777.     return SUCCESS;
  778.   }
  779.   // legacy support
  780.   async command result_t SetListeningMode(uint8_t power) {
  781.     return call SetListeningMode(power);
  782.   }
  783.   /**
  784.    * Gets the state of low power listening on the chipcon radio.
  785.    * @return Current low power listening state value
  786.    */
  787.   async command uint8_t LowPowerListening.GetListeningMode() {
  788.     return lplpower;
  789.   }
  790.   // legacy support
  791.   async command uint8_t GetListeningMode() {
  792.     return call LowPowerListening.GetListeningMode();
  793.   } 
  794.   /**
  795.    * Set the preamble length of outgoing packets
  796.    *
  797.    * @param bytes length of the preamble in bytes
  798.    * @return SUCCESS if the preamble length was successfully changed
  799.    */
  800.   async command result_t LowPowerListening.SetPreambleLength(uint16_t bytes) {
  801.     result_t result = FAIL;
  802.     atomic {
  803.       if (RadioState != TX_STATE) {
  804.         preamblelen = bytes;
  805.         result = SUCCESS;
  806.       }
  807.     }
  808.     return result;
  809.   }
  810.   /**
  811.    * Get the preamble length of outgoing packets
  812.    *
  813.    * @return length of the preamble in bytes
  814.    */
  815.   async command uint16_t LowPowerListening.GetPreambleLength() {
  816.     return preamblelen;
  817.   }
  818.   /**
  819.    * Set the check interval (time between waking up and sampling
  820.    * the radio for activity in low power listening)
  821.    *
  822.    * @param ms check interval in milliseconds
  823.    * @return SUCCESS if the check interval was successfully changed
  824.    */
  825.   async command result_t LowPowerListening.SetCheckInterval(uint16_t ms) {
  826.     // sleep time will go into effect after the next wakeup time
  827.     atomic sleeptime = ms;
  828.     return SUCCESS;
  829.   }
  830.   /**
  831.    * Get the check interval currently used by low power listening
  832.    *
  833.    * @return length of the check interval in milliseconds
  834.    */
  835.   async command uint16_t LowPowerListening.GetCheckInterval() {
  836.     return sleeptime;
  837.   }
  838.   event result_t SquelchTimer.fired() {
  839.     char currentRadioState;
  840.     atomic currentRadioState = RadioState;
  841.     if (currentRadioState == IDLE_STATE) {
  842.       atomic RSSIInitState = currentRadioState;
  843.       call RSSIADC.getData();
  844.     }
  845.     return SUCCESS;
  846.   }
  847.   event result_t WakeupTimer.fired() {
  848.     uint8_t currentRadioState;
  849.     if (lplpower == 0)
  850.       return SUCCESS;
  851.     
  852.     atomic currentRadioState = RadioState;
  853.     switch(currentRadioState) {
  854.     case IDLE_STATE:
  855.       if (!bTxPending || (enableHCL && IsHCL(currentSlot))) { // changed here for hcl optimization
  856.         atomic {
  857.           RadioState = POWER_DOWN_STATE;
  858.           call SpiByteFifo.disableIntr();
  859.         }
  860.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  861.         call SquelchTimer.stop();
  862.         call CC1000StdControl.stop();
  863.       } else {
  864.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  865.       }
  866.       break;
  867.     case POWER_DOWN_STATE:
  868.       atomic RadioState = PULSE_CHECK_STATE;
  869.       pulse_check_count = 0;
  870.       call CC1000StdControl.start();
  871.       call CC1000Control.BIASOn();
  872.       call WakeupTimer.start(TIMER_ONE_SHOT, 1);
  873.       return SUCCESS;
  874.       break;
  875.     case PULSE_CHECK_STATE:
  876.       call CC1000Control.RxMode();
  877.       if(!(call RSSIADC.getData())){
  878.         call WakeupTimer.start(TIMER_ONE_SHOT, TIME_BETWEEN_CHECKS);
  879.         atomic RadioState = POWER_DOWN_STATE;
  880.       }
  881.       else {
  882.         TOSH_uwait(80);
  883.       }
  884.       call CC1000StdControl.stop();
  885.       pulse_check_sum ++;
  886.       break;
  887.     default:
  888.       call WakeupTimer.start(TIMER_ONE_SHOT, 5);
  889.     }
  890.     return SUCCESS;
  891.   }
  892.   task void IdleTimerTask(){
  893.     if (iSquelchCount > CC1K_SquelchCount)
  894.       call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  895.     else
  896.       call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  897.     call WakeupTimer.start(TIMER_ONE_SHOT, TIME_AFTER_CHECK);
  898.     /*if(pulse_check_sum > CHECK_MA_COUNT){
  899.       power_sum ++;
  900.       pulse_check_sum -= CHECK_MA_COUNT;
  901.       }
  902.       if(send_sum > SEND_MA_COUNT){
  903.       power_sum ++;
  904.       send_sum -= SEND_MA_COUNT;
  905.       }
  906.       if(receive_sum > RECEIVE_MA_COUNT){
  907.       power_sum ++;
  908.       receive_sum -= RECEIVE_MA_COUNT;
  909.       }*/
  910.   }
  911.   //added by Mahesh
  912.   event result_t TDMATimer.fired(){
  913.     call TDMATimer.start(TIMER_ONE_SHOT, slotMultiplier);
  914.     slotNum++;
  915.     atomic currentMAC = ZMAC;
  916.     atomic{
  917.       currentSlot = slotNum & (localFrameLength - 1);
  918.       globalSlot = slotNum & (globalFrameLength - 1);
  919. #ifdef ZMAC_TIMER
  920.       SODbg(DBG_USR2,"*************Timer fired with current slot = %u, own slot = %un", currentSlot, ownSlot);
  921. #endif 
  922.       if(HCLselect){
  923.         slots_since_ecnsend ++;
  924.         slots_since_ecnrecv ++;
  925.         slots_since_ecncheck++;
  926.         if((packetsSent > ECNMINPACKETS) && (slots_since_ecncheck >= ECNCHECKPERIOD)){
  927.           double currentLoss = (double)congBackOffs/packetsSent;
  928.           avgLoss = ALPHA * (currentLoss) + (1 - ALPHA) * avgLoss;
  929. #ifdef ZMAC_ECN
  930.           SODbg(DBG_USR2,"#####################Congestion Statistics: %i / %i, %in", congBackOffs, packetsSent, (uint16_t) avgLoss);
  931. #endif
  932.           slots_since_ecncheck = 0;
  933.           congBackOffs = 0;
  934.           packetsSent = 0;
  935.           if((avgLoss > ECNTHRESHOLD) && (slots_since_ecnsend >= ECNSENDPERIOD)){
  936.             ecnMsgType *ecnMsgPtr = (ecnMsgType *) ecnMsgHdr.data;
  937. #ifdef ZMAC_ECN
  938.             SODbg(DBG_USR2,"Setting ECN flagn");
  939. #endif
  940.             // change by acw, go to ecn myself if sending ecn
  941.             atomic enableHCL = TRUE;
  942.             slots_since_ecnrecv = 0;
  943.             // change by acw ends
  944.             ecnMsgPtr->nextHop = nextHop;
  945.             if(!pureHCL)
  946.               ecnPending = TRUE;
  947.           }
  948.         }
  949.         if((enableHCL) && (slots_since_ecnrecv >= ECNEXPIREPERIOD)){
  950.           if(!pureHCL)
  951.             enableHCL = FALSE;
  952. #ifdef ZMAC_ECN
  953.           SODbg(DBG_USR2,"ECN expired, into LCL againn");
  954. #endif
  955.         }
  956.         
  957. #ifdef ZMAC_ECN
  958.         if(enableHCL)
  959.           SODbg(DBG_USR2,"Current slot %i **********************n",currentSlot);
  960. #endif
  961. #ifdef ZMAC_ECN
  962.         if(enableHCL && IsHCL(globalSlot) && ownSlot != currentSlot)
  963.           SODbg(DBG_USR2,"***** ****** ****** ****** Current slot %i HCLn",currentSlot);
  964. #endif
  965.       }
  966.       // changed here for hcl optimization
  967.       if((RadioState == POWER_DOWN_STATE) || (RadioState == DISABLED_STATE)){
  968.         if (bTxPending && (!enableHCL || !IsHCL(currentSlot))) { // bug fixed by Dr. Rhee
  969.           call CC1000Control.RxMode();
  970.           RadioState = IDLE_STATE;
  971.           call SpiByteFifo.rxMode();     // SPI to miso
  972.           call SpiByteFifo.enableIntr(); // enable spi interrupt
  973.           post IdleTimerTask();
  974.         }
  975.       }
  976.       if(bTxPending){
  977.         sMacDelay = getZMACBackoff(sMacDelay);
  978. #ifdef ZMAC_BACKOFF
  979.         SODbg(DBG_USR2,"TDMATimerFired: backoff %un", sMacDelay);
  980. #endif
  981.       }
  982.     }
  983.     return SUCCESS;
  984.   }
  985.  
  986.   command result_t StdControl.stop() {
  987.     atomic RadioState = DISABLED_STATE;
  988.     call SquelchTimer.stop();
  989.     call WakeupTimer.stop();
  990.     call CC1000StdControl.stop();
  991.     call SpiByteFifo.disableIntr(); // disable spi interrupt
  992.     return SUCCESS;
  993.   }
  994.   command result_t StdControl.start() {
  995.     uint8_t currentRadioState;
  996.     atomic currentRadioState = RadioState;
  997.     call SClock.SetRate(MAX_VAL,CLK_DIV_64);
  998.     if (currentRadioState == DISABLED_STATE) {
  999.       atomic {
  1000.         rxbufptr->length = 0;
  1001.         RadioState  = IDLE_STATE;
  1002.         bTxPending = bTxBusy = FALSE;
  1003.         sMacDelay = -1;
  1004.         if(SLEEPTIME > 0){
  1005.           sleeptime = SLEEPTIME;
  1006.           preamblelen = PREAMBLELEN;
  1007.         } else{
  1008.           lplpower = lplpowertx = 0;
  1009.           sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) |
  1010.                        PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1]));
  1011.           preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) |
  1012.                          PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  1013.         }
  1014. /*         sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) | */
  1015. /*                      PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1])); */
  1016. /*         preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) | */
  1017. /*                        PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1])); */
  1018.       }
  1019.       // all power on, captain!
  1020.       rxbufptr->length = 0;
  1021.       atomic RadioState = IDLE_STATE;
  1022.       call CC1000StdControl.start();
  1023.       call CC1000Control.BIASOn();
  1024.       call SpiByteFifo.rxMode(); // SPI to miso
  1025.       call CC1000Control.RxMode();
  1026.       if (iSquelchCount > CC1K_SquelchCount)
  1027.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  1028.       else
  1029.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  1030.       call SpiByteFifo.enableIntr(); // enable spi interrupt
  1031.       if (lplpower > 0) {
  1032.         // set a time to start sleeping after measuring the noise floor
  1033.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_SquelchIntervalSlow);
  1034.       }
  1035.     }
  1036.     return SUCCESS;
  1037.   }
  1038.   command result_t Send.send(TOS_MsgPtr pMsg) {
  1039.     result_t Result = SUCCESS;
  1040.     uint8_t currentRadioState = 0;
  1041.    
  1042.     atomic {
  1043.       if (bTxBusy) {
  1044.         Result = FAIL;
  1045. #ifdef ZMAC_DEBUG
  1046.         //        SODbg(DBG_USR2, "Busy sending the message of type %u!n", txbufptr->type);
  1047. #endif
  1048.       } else {
  1049.         bTxBusy = TRUE;
  1050.         txbufptr = pMsg;
  1051.         txlength = pMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
  1052.         if(bCCAEnable){ // initially back off [1,32] bytes (approx 2/3 packet)
  1053.           if(currentMAC == BMAC)
  1054.             sMacDelay = signal MacBackoff.initialBackoff(pMsg);
  1055.           else
  1056.             sMacDelay = getZMACBackoff(0);
  1057.         } else
  1058.           sMacDelay = 0;
  1059. #ifdef ZMAC_BACKOFF
  1060.         SODbg(DBG_USR2, "SendMSG(): Need to send type %u, myslot %u, current slot %u backoff %un",
  1061.               txbufptr->type, ownSlot, currentSlot, sMacDelay);
  1062. #endif
  1063.         bTxPending = TRUE;
  1064.       }
  1065.       currentRadioState = RadioState;
  1066.     }
  1067.     if (Result) {
  1068.       if (currentRadioState == POWER_DOWN_STATE){ //{ && (!enableHCL || !IsHCL(currentSlot))) {       // if we're off, start the radio
  1069.         atomic RadioState = IDLE_STATE;         // disable wakeup timer
  1070.         call WakeupTimer.stop();
  1071.         call CC1000StdControl.start();
  1072.         call CC1000Control.BIASOn();
  1073.         call CC1000Control.RxMode();
  1074.         call SpiByteFifo.rxMode(); // SPI to miso
  1075.         call SpiByteFifo.enableIntr(); // enable spi interrupt
  1076.         if (iSquelchCount > CC1K_SquelchCount)
  1077.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  1078.         else
  1079.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  1080.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
  1081.       }
  1082.     }
  1083.     return Result;
  1084.   }
  1085.   
  1086.   /**********************************************************
  1087.    * make a spibus interrupt handler
  1088.    * needs to handle interrupts for transmit delay
  1089.    * and then go into byte transmit mode with
  1090.    *   timer1 baudrate delay as interrupt handler
  1091.    * else SODbg(DBG_USR2,"Sending Packet ..");
  1092.    * needs to handle interrupts for byte read and detect preamble
  1093.    *  then handle reading a packet
  1094.    * PB - We can use this interrupt handler as a transmit scheduler
  1095.    * because the CC1000 continuously clocks in data, regarless
  1096.    * of whether it's good or not.  Thus, this routine will be called
  1097.    * on every 8 ticks of DCLK. 
  1098.    **********************************************************/
  1099.   async event result_t SpiByteFifo.dataReady(uint8_t data_in) {
  1100.     GTime loctime;
  1101.     signal RadioSendCoordinator.blockTimer();
  1102.     signal RadioReceiveCoordinator.blockTimer();
  1103.      
  1104.     if (bInvertRxData)
  1105.       data_in = ~data_in;
  1106. #ifdef ENABLE_UART_DEBUG
  1107.     UARTPutChar(RadioState);
  1108. #endif
  1109.     switch (RadioState) {
  1110.     case TX_STATE:
  1111.       {
  1112.         call SpiByteFifo.writeByte(NextTxByte);
  1113.         TxByteCnt++;
  1114.         switch (RadioTxState) {
  1115.           
  1116.         case TXSTATE_PREAMBLE:
  1117.           send_sum ++;
  1118.           if (!(TxByteCnt < preamblelen)||
  1119.               (txbufptr->strength == 0xffff && TxByteCnt >= PREAMBLE_LENGTH_TO_BASE)) {
  1120.             NextTxByte = SYNC_BYTE;
  1121.             RadioTxState = TXSTATE_SYNC;
  1122. #ifdef ZMAC_ECN
  1123.             SODbg(DBG_USR2,"Sent packet in slot %in",currentSlot);
  1124.             SODbg(DBG_USR2, "ishcl = %un", IsHCL(currentSlot));
  1125. #endif
  1126.           }
  1127.           break;
  1128.         case TXSTATE_SYNC:
  1129.           send_sum ++;
  1130.           NextTxByte = NSYNC_BYTE;
  1131.           RadioTxState = TXSTATE_DATA;
  1132.           TxByteCnt = -1;
  1133.           if(txbufptr->type == SYNCTYPE){ // allow sync messages
  1134.             syncMsgType *syncMsgPtr = (syncMsgType *) txbufptr->data;
  1135.             call SClock.getTime(&loctime);
  1136.             syncMsgPtr->mticks = loctime.mticks;
  1137.             syncMsgPtr->sticks = loctime.sticks;
  1138.             syncMsgPtr->trust = TRUST_FACTOR;
  1139.             syncMsgPtr->sender = TOS_LOCAL_ADDRESS;
  1140.           }
  1141.           // for Time Sync services
  1142.           signal RadioSendCoordinator.startSymbol(8, 0, txbufptr);
  1143.           break;
  1144.         case TXSTATE_DATA:
  1145.           send_sum ++;
  1146.           if ((uint8_t)(TxByteCnt) < txlength){
  1147.             if((txbufptr->type == SYNCTYPE) && (TxByteCnt == 5)){ // 5 = offset of timestamp
  1148.               syncMsgType *syncMsgPtr = (syncMsgType *) txbufptr->data;
  1149.               call SClock.getTime(&loctime);
  1150.               AddTime(&loctime, &loctime, &constOffset);
  1151.               syncMsgPtr->mticks = loctime.mticks;
  1152.               syncMsgPtr->sticks = loctime.sticks;
  1153.             }
  1154.             NextTxByte = ((uint8_t *)txbufptr)[(TxByteCnt)];
  1155.             usRunningCRC = crcByte(usRunningCRC,NextTxByte);
  1156.             signal RadioSendCoordinator.byte(txbufptr, (uint8_t)TxByteCnt); // Time Sync
  1157.           }
  1158.           else {
  1159.             NextTxByte = (uint8_t)(usRunningCRC);
  1160.             RadioTxState = TXSTATE_CRC;
  1161.           }
  1162.           break;
  1163.         case TXSTATE_CRC:
  1164.           send_sum ++;
  1165.           NextTxByte = (uint8_t)(usRunningCRC>>8);
  1166.           RadioTxState = TXSTATE_FLUSH;
  1167.           TxByteCnt = 0;
  1168.           break;
  1169.         case TXSTATE_FLUSH:
  1170.           send_sum ++;
  1171.           if (TxByteCnt > 3) {
  1172.             TxByteCnt = 0;
  1173. #ifdef ZMAC_DEBUG
  1174.             // SODbg(DBG_USR2,"Came heren");
  1175. #endif
  1176.             if (bAckEnable)
  1177.               RadioTxState = TXSTATE_WAIT_FOR_ACK;         
  1178.             else {
  1179. #ifdef ZMAC_DEBUG
  1180.               // SODbg(DBG_USR2,"came inside: current MAC: %i ackenabled :%i,ecnPending: %i ecnforward %i ecnSENT %in",currentMAC,bAckEnable,ecnPending,ecnforward,sentECN);
  1181. #endif
  1182.               packetsSent ++;
  1183.               call SpiByteFifo.rxMode();
  1184.               call CC1000Control.RxMode();
  1185.               RadioTxState = TXSTATE_DONE;
  1186.             }
  1187.           }
  1188.           break;
  1189.         case TXSTATE_WAIT_FOR_ACK:
  1190.           if(TxByteCnt == 1){
  1191.             send_sum ++;
  1192.             call SpiByteFifo.rxMode();
  1193.             call CC1000Control.RxMode();
  1194.             break;
  1195.           }
  1196.           receive_sum ++;
  1197.           if (TxByteCnt > 3) {
  1198.             RadioTxState = TXSTATE_READ_ACK;
  1199.             TxByteCnt = 0;
  1200.             search_word = 0;
  1201.           }
  1202.           break;
  1203.         case TXSTATE_READ_ACK:
  1204.           {
  1205.             uint8_t i;
  1206.             receive_sum ++;
  1207.             for(i = 0; i < 8; i ++){
  1208.               search_word <<= 1;
  1209.               if(data_in & 0x80) search_word |=  0x1;
  1210.               data_in <<= 1;
  1211.               if (search_word == 0xba83){
  1212.                 txbufptr->ack = 1;
  1213.                 RadioTxState = TXSTATE_DONE;
  1214. #ifdef ZMAC_DEBUG
  1215.                 //                SODbg(DBG_USR2,"received ackn");
  1216. #endif
  1217.                 return SUCCESS;
  1218.               }
  1219.             }
  1220.           }
  1221.           if(TxByteCnt >= MAX_ACK_WAIT){   
  1222.             txbufptr->ack = 0;  
  1223. #ifdef ZMAC_DEBUG
  1224.             //       SODbg(DBG_USR2,"did not receive ack %i %i %in",lostacks,packetsSent,avgLoss * 100);
  1225. #endif
  1226.             RadioTxState = TXSTATE_DONE;
  1227.           }
  1228.           break;
  1229.         case TXSTATE_DONE:
  1230.         default:
  1231.           bTxPending = FALSE;
  1232.           if((txbufptr->type == ECNTYPE) || (txbufptr->type == SYNCTYPE)){
  1233. #ifdef ZMAC_ECN
  1234.             ecnForwardMsgType *ecnForwardMsgPtr = (ecnForwardMsgType *) txbufptr->data;
  1235.             if(txbufptr->type == ECNTYPE && ecnForwardMsgPtr->hopCount == 1)
  1236.               SODbg(DBG_USR2,"Successfully forwarded ECNn");
  1237. #endif
  1238.             bAckEnable = ackOrig;
  1239.           }
  1240. #ifdef ZMAC_BACKOFF
  1241.           SODbg(DBG_USR2, "Sent one packet of type %u, myslot %u, current slot %u!n", txbufptr->type,
  1242.                 ownSlot, currentSlot);
  1243. #endif
  1244.           if(post PacketSent()) {
  1245.             // If the post operation succeeds, goto Idle
  1246.             // otherwise, we'll try again.
  1247. #ifdef ZMAC_DEBUG
  1248.             //  SODbg(DBG_USR2,"Packet type %in",txbufptr->type);
  1249. #endif
  1250.             RadioState = IDLE_STATE;
  1251.             pktsLastSync++;
  1252.             RSSIInitState = RadioState;
  1253.             call RSSIADC.getData();
  1254.           }
  1255.           break;
  1256.         }
  1257.       }
  1258.       break;
  1259.     case DISABLED_STATE:
  1260.       break;
  1261.     case IDLE_STATE: 
  1262.       {
  1263.         receive_sum ++;
  1264.         if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  1265.           PreambleCount++;
  1266.           if (PreambleCount > CC1K_ValidPrecursor) {
  1267.             PreambleCount = SOFCount = 0;
  1268.             RxBitOffset = RxByteCnt = 0;
  1269.             usRunningCRC = 0;
  1270.             rxlength = MSG_DATA_SIZE-2;
  1271.             RadioState = SYNC_STATE;
  1272.           }
  1273.         } else {
  1274.           if ((currentMAC == BMAC) || (enableHCL == FALSE) || (!IsHCL(currentSlot))) {
  1275.             if((bTxPending) && (--sMacDelay <= 0)){
  1276.               RadioState = PRETX_STATE;
  1277.               RSSIInitState = PRETX_STATE;
  1278.               bRSSIValid = FALSE;
  1279.               iRSSIcount = 0;
  1280.               PreambleCount = 0;
  1281.               call RSSIADC.getData();
  1282.             }
  1283.           } else{
  1284. #ifdef ZMAC_ECN
  1285.             SODbg(DBG_USR2, "&&&&&&&&&&&&&&&&&&&&& ishcl = %un", IsHCL(currentSlot));
  1286. #endif
  1287.           }
  1288.         }
  1289.       }
  1290.       break;
  1291.     case PRETX_STATE:
  1292.       {
  1293.         receive_sum ++;
  1294.         if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  1295.           // Back to the penalty box.
  1296.           sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
  1297. #ifdef ZMAC_BACKOFF
  1298.           SODbg(DBG_USR2,"SpiDataReady: detected preamble - backoff %un", sMacDelay);
  1299. #endif
  1300.           RadioState = IDLE_STATE;
  1301.         }
  1302.       }
  1303.       break;
  1304.     case SYNC_STATE:
  1305.       {
  1306.         // draw in the preamble bytes and look for a sync byte
  1307.         // save the data in a short with last byte received as msbyte
  1308.         //    and current byte received as the lsbyte.
  1309.         // use a bit shift compare to find the byte boundary for the sync byte
  1310.         // retain the shift value and use it to collect all of the packet data
  1311.         // check for data inversion, and restore proper polarity 
  1312.         // XXX-PB: Don't do this.
  1313.         uint8_t i;
  1314.         receive_sum ++;
  1315.         if ((data_in == 0xaa) || (data_in == 0x55)) {
  1316.           // It is actually possible to have the LAST BIT of the incoming
  1317.           // data be part of the Sync Byte.  SO, we need to store that
  1318.           // However, the next byte should definitely not have this pattern.
  1319.           // XXX-PB: Do we need to check for excessive preamble?
  1320.           RxShiftBuf.MSB = data_in;
  1321.         }
  1322.         else {
  1323.           // TODO: Modify to be tolerant of bad bits in the preamble...
  1324.           uint16_t usTmp;
  1325.           switch (SOFCount) {
  1326.           case 0:
  1327.             RxShiftBuf.LSB = data_in;
  1328.             break;
  1329.   
  1330.           case 1:
  1331.           case 2: 
  1332.           case 3: 
  1333.           case 4: 
  1334.           case 5: 
  1335.             // bit shift the data in with previous sample to find sync
  1336.             usTmp = RxShiftBuf.W;
  1337.             RxShiftBuf.W <<= 8;
  1338.             RxShiftBuf.LSB = data_in;
  1339.             for(i=0;i<8;i++) {
  1340.               usTmp <<= 1;
  1341.               if(data_in & 0x80)
  1342.                 usTmp  |=  0x1;
  1343.               data_in <<= 1;
  1344.               // check for sync bytes
  1345.               if (usTmp == SYNC_WORD) {
  1346.                 if (rxbufptr->length !=0) {
  1347.                   call Leds.redToggle();
  1348.                   RadioState = IDLE_STATE;
  1349.                 }
  1350.                 else {
  1351.                   RadioState = RX_STATE;
  1352.                   RSSIInitState = RX_STATE;
  1353.                   call RSSIADC.getData();
  1354.                   RxBitOffset = 7-i;
  1355.                   // For time sync services
  1356.                   signal RadioReceiveCoordinator.startSymbol(8, RxBitOffset, rxbufptr); 
  1357.                 }
  1358.                 break;
  1359.               }
  1360.             }
  1361.             break;
  1362.           default:
  1363.             // We didn't find it after a reasonable number of tries, so....
  1364.             RadioState = IDLE_STATE;  // Ensures we wait till the end of the transmission
  1365.             break;
  1366.           }
  1367.           SOFCount++;
  1368.         }
  1369.       }
  1370.       break;
  1371.       //  collect the data and shift into double buffer
  1372.       //  shift out data by correct offset
  1373.       //  invert the data if necessary
  1374.       //  stop after the correct packet length is read
  1375.       //  return notification to upper levels
  1376.       //  go back to idle state
  1377.     case RX_STATE:
  1378.       {
  1379.         char Byte;
  1380.         receive_sum ++;
  1381.         RxShiftBuf.W <<=8;
  1382.         RxShiftBuf.LSB = data_in;
  1383.         Byte = (RxShiftBuf.W >> RxBitOffset);
  1384.         ((char*)rxbufptr)[(int)RxByteCnt] = Byte;
  1385.         RxByteCnt++;
  1386.         signal RadioReceiveCoordinator.byte(rxbufptr, (uint8_t)RxByteCnt);
  1387.         if (RxByteCnt < rxlength) {
  1388.           usRunningCRC = crcByte(usRunningCRC,Byte);
  1389.           if (RxByteCnt == (offsetof(struct TOS_Msg,length) + 
  1390.                             sizeof(((struct TOS_Msg *)0)->length))) {
  1391.             rxlength = rxbufptr->length;
  1392.             if (rxlength > TOSH_DATA_LENGTH) {
  1393.               // The packet's screwed up, so just dump it
  1394.               rxbufptr->length = 0;
  1395.               RadioState = IDLE_STATE;  // Waits till end of transmission
  1396.               return SUCCESS;
  1397.             }
  1398.             //Add in the header size
  1399.             rxlength += offsetof(struct TOS_Msg,data);
  1400.           }
  1401.         }
  1402.         else if (RxByteCnt == rxlength) {
  1403.           if(rxbufptr->type == SYNCTYPE) // got all bytes of time stamp !
  1404.             getTimeDiff();
  1405.           usRunningCRC = crcByte(usRunningCRC,Byte);
  1406.           // Shift index ahead to the crc field.
  1407.           RxByteCnt = offsetof(struct TOS_Msg,crc);
  1408.         }
  1409.         else if (RxByteCnt >= MSG_DATA_SIZE) { 
  1410.           // Packet filtering based on bad CRC's is done at higher layers.
  1411.           // So sayeth the TOS weenies.
  1412.           if (rxbufptr->crc == usRunningCRC) {
  1413.             if(rxbufptr->type == SYNCTYPE)
  1414.               post adjustTime();
  1415.             rxbufptr->crc = 1;
  1416.             
  1417.             if(bAckEnable && (rxbufptr->addr == TOS_LOCAL_ADDRESS)){
  1418.               RadioState = SENDING_ACK; 
  1419.               call CC1000Control.TxMode();
  1420.               call SpiByteFifo.txMode();
  1421.               call SpiByteFifo.writeByte(0xaa);
  1422.               RxByteCnt = 0;
  1423.               return SUCCESS; 
  1424.             }
  1425.           } else {
  1426.             rxbufptr->crc = 0;
  1427.           }
  1428.           call SpiByteFifo.disableIntr();
  1429.   
  1430.           RadioState = IDLE_STATE; //DISABLED_STATE;
  1431.           if((currentMAC == ZMAC) && (bTxPending)){ //Ajit - reset timer when time slot boundary
  1432.             sMacDelay = getZMACBackoff(sMacDelay);
  1433. #ifdef ZMAC_BACKOFF
  1434.             SODbg(DBG_USR2,"JustAfterReceive: backoff %u mySlot %u currentSlot %un", sMacDelay,
  1435.                   ownSlot, currentSlot);
  1436. #endif
  1437.           }
  1438.           rxbufptr->strength = usRSSIVal;
  1439.           if (!(post PacketRcvd())) {
  1440.             // If there are insufficient resources to process the incoming packet
  1441.             // we drop it
  1442.             rxbufptr->length = 0;
  1443.             RadioState = IDLE_STATE;
  1444.             call SpiByteFifo.enableIntr();
  1445.           }
  1446.           RSSIInitState = RadioState;
  1447.           call RSSIADC.getData();
  1448.         }
  1449.       }
  1450.       break;
  1451.     case SENDING_ACK:
  1452.       {
  1453.         send_sum ++;
  1454.         RxByteCnt++;
  1455.         if (RxByteCnt >= ACK_LENGTH) { 
  1456.           call CC1000Control.RxMode();
  1457.           call SpiByteFifo.rxMode();
  1458.           call SpiByteFifo.disableIntr();
  1459.           RadioState = IDLE_STATE; //DISABLED_STATE;
  1460.           rxbufptr->strength = usRSSIVal;
  1461.           if (!(post PacketRcvd())) {
  1462.             rxbufptr->length = 0;
  1463.             RadioState = IDLE_STATE;
  1464.             call SpiByteFifo.enableIntr();
  1465.           }
  1466.         }else if(RxByteCnt >= ACK_LENGTH - sizeof(ack_code)){
  1467.           call SpiByteFifo.writeByte(ack_code[RxByteCnt + sizeof(ack_code) - ACK_LENGTH]);
  1468.         }
  1469.       }
  1470.       break;
  1471.     default:
  1472.       break;
  1473.     }
  1474.     if(pulse_check_sum > CHECK_MA_COUNT){
  1475.       power_sum ++;
  1476.       sp_sum++;
  1477.       pulse_check_sum -= CHECK_MA_COUNT;
  1478.     }
  1479.     if(send_sum > SEND_MA_COUNT){
  1480.       power_sum ++;
  1481.       tx_sum++;
  1482.       send_sum -= SEND_MA_COUNT;
  1483.     }
  1484.     if(receive_sum > RECEIVE_MA_COUNT){
  1485.       power_sum ++;
  1486.       rx_sum++;
  1487.       receive_sum -= RECEIVE_MA_COUNT;
  1488.     }
  1489.     return SUCCESS;
  1490.   }
  1491.   task void SleepTimerTask(){
  1492.     call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  1493.   }
  1494.   async event result_t RSSIADC.dataReady(uint16_t data) { 
  1495.     atomic{
  1496.       uint8_t currentRadioState;
  1497.       // TOSH_CLR_PW3_PIN();
  1498.       currentRadioState = RadioState;
  1499.       // find the maximum RSSI value over CC1K_MAX_RSSI_SAMPLES
  1500.       switch(currentRadioState) {
  1501.       case IDLE_STATE:
  1502.         if (RSSIInitState == IDLE_STATE) {
  1503.           atomic usTempSquelch = data;
  1504.           post adjustSquelch();
  1505.         }
  1506.         RSSIInitState = NULL_STATE;
  1507.         break;
  1508.           
  1509.       case RX_STATE:
  1510.         if (RSSIInitState == RX_STATE) {
  1511.           atomic usRSSIVal = data;
  1512.         }
  1513.         RSSIInitState = NULL_STATE;
  1514.         break;
  1515.         
  1516.       case PRETX_STATE:
  1517.         iRSSIcount++;
  1518.         
  1519.         // if the channel is clear or CCA is disabled, GO GO GO!
  1520.         if (((data > (usSquelchVal + CC1K_SquelchBuffer)) ||
  1521.              (!bCCAEnable)) && (RSSIInitState == PRETX_STATE)) { 
  1522.           call SpiByteFifo.writeByte(0xaa);
  1523.           call CC1000Control.TxMode();
  1524.           call SpiByteFifo.txMode();
  1525.           
  1526.           usRSSIVal = data;
  1527.           iRSSIcount = CC1K_MaxRSSISamples;
  1528.           bRSSIValid = TRUE;
  1529.           TxByteCnt = 0;
  1530.           usRunningCRC = 0;
  1531.           RadioState = TX_STATE;
  1532.           RadioTxState = TXSTATE_PREAMBLE;
  1533.           NextTxByte = 0xaa;
  1534.           RSSIInitState = NULL_STATE;
  1535.         }
  1536.         else {
  1537.           RSSIInitState = NULL_STATE;
  1538.           if (iRSSIcount == CC1K_MaxRSSISamples) {
  1539.             sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
  1540. #ifdef ZMAC_BACKOFF
  1541.             SODbg(DBG_USR2,"adcDataReady: channel busy, backoff %un", sMacDelay);
  1542. #endif
  1543.             RadioState = IDLE_STATE;
  1544.           }
  1545.           else {
  1546.             RSSIInitState = currentRadioState;
  1547.             call RSSIADC.getData();
  1548.           }
  1549.         }
  1550.         break;
  1551.         
  1552.       case PULSE_CHECK_STATE:
  1553.         atomic{
  1554.           uint8_t done = 0;
  1555.           uint16_t threshold = call GetSquelch();
  1556.           threshold = threshold - (call GetSquelch() >> 2);
  1557.           if(data > threshold){
  1558.             // adjust the noise floor level
  1559.             atomic usTempSquelch = data;
  1560.             post adjustSquelch();
  1561.             
  1562.           }else if(pulse_check_count > 5){
  1563.             //go to the idle state since no outliers were found
  1564.             call CC1000Control.RxMode();
  1565.             RadioState = IDLE_STATE;
  1566.             call SpiByteFifo.rxMode();     // SPI to miso
  1567.             call SpiByteFifo.enableIntr(); // enable spi interrupt
  1568.             post IdleTimerTask();
  1569.             done = 1;
  1570.             
  1571.           }else {
  1572.             call CC1000Control.RxMode();
  1573.             if(call RSSIADC.getData()){
  1574.               TOSH_uwait(80);
  1575.               pulse_check_count ++;
  1576.               done = 1;
  1577.             }
  1578.             pulse_check_sum ++;
  1579.             call CC1000StdControl.stop();
  1580.           }
  1581.           // changed here for hcl optimization
  1582.           if (bTxPending && (!enableHCL || !IsHCL(currentSlot))) { // bug fixed by Dr. Rhee
  1583.             //go to the idle state since no outliers were found
  1584.             call CC1000Control.RxMode();
  1585.             RadioState = IDLE_STATE;
  1586.             call SpiByteFifo.rxMode();     // SPI to miso
  1587.             call SpiByteFifo.enableIntr(); // enable spi interrupt
  1588.             post IdleTimerTask();
  1589.             done = 1;
  1590.           }
  1591.           if(done == 0){
  1592.             post SleepTimerTask();
  1593.             RadioState = POWER_DOWN_STATE;
  1594.             call SpiByteFifo.disableIntr();
  1595.           }
  1596.         }
  1597.         //go to the power down state
  1598.         break;
  1599.       default:
  1600.       }
  1601.     }
  1602.     return SUCCESS;
  1603.   }
  1604.   // XXX:JP- for testing the mac layer squlech value
  1605.   async command uint16_t GetSquelch() {
  1606.     return usSquelchVal;
  1607.   }
  1608.   // XXX:JP- for testing the mac layer power consumption
  1609.   async command uint16_t GetPower() {
  1610.     return power_sum;
  1611.   }
  1612.   async command uint16_t GetDataSent() {
  1613.     return dataSent;
  1614.   }
  1615.   async command result_t ResetDataSent() {
  1616.     dataSent = 0;
  1617.     return SUCCESS;
  1618.   }
  1619.   async command uint16_t GetPower_tx() {
  1620.     return tx_sum;
  1621.   }
  1622.   async command uint16_t GetPower_rx() {
  1623.     return rx_sum;
  1624.   }
  1625.   async command uint16_t GetPower_sp() {
  1626.     return sp_sum;
  1627.   }
  1628.   async command result_t ResetPower() {
  1629.     power_sum = 0;
  1630.     pulse_check_sum = 0;
  1631.     send_sum = 0;
  1632.     receive_sum = 0;
  1633.     sp_sum = 0;
  1634.     tx_sum = 0;
  1635.     rx_sum = 0;
  1636.     return SUCCESS;
  1637.   }
  1638.   async command result_t MacControl.enableAck() {
  1639.     atomic bAckEnable = TRUE;
  1640.     return SUCCESS;
  1641.   }
  1642.   async command result_t MacControl.disableAck() {
  1643.     atomic bAckEnable = FALSE;
  1644.     return SUCCESS;
  1645.   }
  1646.   async command result_t MacControl.enableCCA() {
  1647.     atomic bCCAEnable = TRUE;
  1648.     return SUCCESS;
  1649.   }
  1650.   async command result_t MacControl.disableCCA() {
  1651.     atomic bCCAEnable = FALSE; 
  1652.     return SUCCESS;
  1653.   }
  1654.   // ***Not yet implemented
  1655.   async command TOS_MsgPtr MacControl.HaltTx() {
  1656.     return 0;
  1657.   }
  1658.   // Default events for radio send/receive coordinators do nothing.
  1659.   // Be very careful using these, you'll break the stack.
  1660.   default async event void RadioSendCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset,
  1661.                                                             TOS_MsgPtr msgBuff) { }
  1662.   default async event void RadioSendCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  1663.   default async event void RadioSendCoordinator.blockTimer() { }
  1664.   default async event void RadioReceiveCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset,
  1665.                                                                TOS_MsgPtr msgBuff) { }
  1666.   default async event void RadioReceiveCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  1667.   default async event void RadioReceiveCoordinator.blockTimer() { }
  1668.   default async event int16_t MacBackoff.initialBackoff(TOS_MsgPtr m){
  1669.     return (call Random.rand() & 0x1F) + 1;
  1670.   }
  1671.   default async event int16_t MacBackoff.congestionBackoff(TOS_MsgPtr m){
  1672.     congBackOffs++;
  1673.     return (call Random.rand() & 0xF) + 1;
  1674.   }
  1675.   /**************SClock Interface********/
  1676.   async event result_t SClock.syncDone(){
  1677.     if(needTimeSync){
  1678.       GTime loctime;
  1679.       uint32_t globalTimeStamp, slotOffset;
  1680.       call SClock.getTime(&loctime);
  1681.       globalTimeStamp = (uint32_t)(loctime.mticks * 568.889 + loctime.sticks * 0.00868056); //in ms
  1682.       slotOffset = (uint32_t) (1.024 * (slotSize - (globalTimeStamp % slotSize))); // in timer units .976562 = 1000/1024
  1683.       slotNum = (uint32_t) (globalTimeStamp/slotSize);
  1684.       currentSlot = slotNum & (localFrameLength - 1);
  1685.       globalSlot = slotNum & (globalFrameLength - 1);
  1686.       if(currentMAC == ZMAC)
  1687.         call TDMATimer.start(TIMER_ONE_SHOT, slotOffset);
  1688.       needTimeSync = FALSE;
  1689.     }
  1690.     return SUCCESS;
  1691.   }
  1692.   async event result_t SClock.fire(uint16_t mticks){ return SUCCESS; }  
  1693. }