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

网络

开发平台:

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.           if(recvEcnMsgPtr->senderAddress == nextHop){  //check forwarding node's address
  438.             //suppress ECN
  439. #ifdef ZMAC_ECN
  440.             SODbg(DBG_USR2,"Suppressed own ECNn");
  441. #endif
  442.             atomic ecnPending = FALSE;
  443.             slots_since_ecnsend = 0;
  444.             slots_since_ecnrecv = 0;
  445.           }
  446.         }
  447.       } else if((pBuf->type != SYNCTYPE) && (pBuf->type != ECNTYPE)){
  448. #ifdef ZMAC_ECN
  449.         //        SODbg(DBG_USR2,"Received packet of type %u, crc = %un", pBuf->type, pBuf->crc);
  450. #endif
  451.         pBuf = signal Receive.receive((TOS_MsgPtr)pBuf);
  452.       }
  453.       
  454.       if (pBuf)
  455.         rxbufptr = pBuf;
  456.       rxbufptr->length = 0;
  457.     }
  458.     call SpiByteFifo.enableIntr();
  459.   }
  460.   
  461.   task void PacketSent() {
  462.     TOS_MsgPtr pBuf; //store buf on stack 
  463.     atomic {
  464.       txbufptr->time = 0;
  465.       pBuf = txbufptr;
  466.     }
  467.       
  468.     if ((txbufptr->type != ECNTYPE) && (txbufptr->type != SYNCTYPE)){
  469.       //      if(txbufptr->type == AM_MULTIHOP)
  470.       //        dataSent++;
  471.       signal Send.sendDone((TOS_MsgPtr)pBuf, SUCCESS);
  472.     } else if(txbufptr->type == SYNCTYPE){
  473. #ifdef ZMAC_DEBUG
  474.       //      SODbg(DBG_USR2, "Sent one sync message $$$$$$$$$n");
  475. #endif
  476.     } else if(txbufptr->type == ECNTYPE){
  477. #ifdef ZMAC_DEBUG
  478.       //      SODbg(DBG_USR2, "Sent one ecn message $$$$$$$$$n");
  479. #endif
  480.     }
  481.       
  482.     atomic bTxBusy = FALSE;
  483.     if(pktsLastSync > SYNC_PERIOD){
  484.       atomic{
  485.         ackOrig = bAckEnable;
  486.         bAckEnable = FALSE;
  487.       }
  488.       call Send.send(&syncMsgHdr);
  489.       pktsLastSync = 0;
  490.     } else if((currentMAC == ZMAC) && (ecnforward == TRUE)){
  491.       atomic{
  492.         ackOrig = bAckEnable;
  493.         bAckEnable = FALSE;
  494.       }
  495.       call Send.send(&ecnForwardMsgHdr);
  496.       atomic ecnforward = FALSE;
  497. #ifdef ZMAC_ECN
  498.       SODbg(DBG_USR2,"Forwarded ECNn");
  499. #endif
  500.     } else if((currentMAC == ZMAC) && (ecnPending == TRUE)){
  501.       atomic{
  502.         ackOrig = bAckEnable;
  503.         bAckEnable = FALSE;
  504.       }
  505.       call Send.send(&ecnMsgHdr);
  506.       atomic ecnPending = FALSE;
  507.       atomic slots_since_ecnsend = 0;
  508. #ifdef ZMAC_ECN
  509.       SODbg(DBG_USR2,"Sent own ECNn");
  510. #endif
  511.     }
  512.   }
  513.   ///**********************************************************
  514.   //* Exported interface functions
  515.   //**********************************************************/
  516.   command void SetDrand.setParent(uint8_t id){ nextHop = id; }
  517.   command result_t SetDrand.Set(nodeInfo *mInfo, uint8_t nHop, nodeInfo *nInfo, uint16_t sSize){
  518.     uint32_t slotOffset = 0, globalTimeStamp = 0;
  519.     GTime loctime;
  520.     uint8_t i = 0;
  521.     slotSize = sSize;
  522.     nextHop = nHop;
  523.     if(0){
  524.       /*       localFrameLength = myInfo->frame; */
  525.       /*       ownSlot = myInfo->slot; */
  526.       /*       nbrInfo = nInfo; */
  527.       /*       for(i = 0; (i < MAX_NBR) && (nbrInfo[i].nodeID != 0xFF); i++) */
  528.       /*         if(nbrInfo[i].bitMap & TWO_HOP) */
  529.       /*           Blacklist(nbrInfo[i].slot, nbrInfo[i].frame); */
  530.     } else{ // USE THIS ONLY FOR TESTING
  531.       for(i = 0 ; i<MAX_NBR ; i++){ // initialize the nbr table
  532.         nbrInfo[i].nodeID = 0xFF;
  533.         nbrInfo[i].slot = 0xFF;
  534.         nbrInfo[i].frame = 0xFF;
  535.         nbrInfo[i].bitMap = 0x0;
  536.       }
  537. #include "nbrTable.h"
  538.       /*       slotSize = sSize; */
  539.       /*       localFrameLength = 8; */
  540.       /*       nextHop = nHop; */
  541.       /*       switch(TOS_LOCAL_ADDRESS){ */
  542.       /*       case 1: */
  543.       /*         ownSlot = 6; */
  544.       /*         break; */
  545.       /*       case 10: */
  546.       /*         ownSlot = 4; */
  547.       /*         break; */
  548.       /*       case 11: */
  549.       /*         ownSlot = 0; */
  550.       /*         break; */
  551.       /*       case 13: */
  552.       /*         ownSlot = 1; */
  553.       /*         break; */
  554.       /*       case 2: */
  555.       /*         ownSlot = 1; */
  556.       /*         break; */
  557.       /*       case 20: */
  558.       /*         ownSlot = 1; */
  559.       /*         break; */
  560.       /*       case 21: */
  561.       /*         ownSlot = 2; */
  562.       /*         break; */
  563.       /*       case 22: */
  564.       /*         ownSlot = 7; */
  565.       /*         break; */
  566.       /*       case 24: */
  567.       /*         ownSlot = 0; */
  568.       /*         break; */
  569.       /*       case 0: */
  570.       /*         ownSlot = 5; */
  571.       /*         break; */
  572.       /*       case 8: */
  573.       /*         ownSlot = 2; */
  574.       /*         break; */
  575.       /*       case 9: */
  576.       /*         ownSlot = 3; */
  577.       /*         break; */
  578.       /*       } */
  579.     }
  580.     localFrameSize = localFrameLength * slotSize;
  581.     globalFrameSize = globalFrameLength * slotSize;
  582.     slotMultiplier = (uint16_t) (slotSize * 1.024);
  583.     call SClock.getTime(&loctime);
  584.     globalTimeStamp = (uint32_t)(loctime.mticks * 568.889 + loctime.sticks * 0.00868056); //in ms
  585.     slotOffset = (uint32_t) (1.024 * (slotSize - (globalTimeStamp % slotSize))); // in timer units .976562 = 1000/1024
  586.     slotNum = (uint32_t) (globalTimeStamp/slotSize);
  587.     currentSlot = slotNum & (localFrameLength - 1);
  588.     globalSlot = slotNum & (globalFrameLength - 1);
  589.     
  590.     call TDMATimer.start(TIMER_ONE_SHOT, slotOffset);
  591. #ifdef ZMAC_TIMER
  592.     // SODbg(DBG_USR2,"Started timer slotsize - offset is %in",slotSize - slotOffset);
  593. #endif
  594.     return SUCCESS; 
  595.   }
  596.   command result_t StdControl.init() {
  597.     char i;
  598.     ecnMsgType *ecnMsgPtr = (ecnMsgType *) ecnMsgHdr.data;
  599.     atomic {
  600.       RadioState = DISABLED_STATE;
  601.       RadioTxState = TXSTATE_PREAMBLE;
  602.       rxbufptr = &RxBuf;
  603.       rxbufptr->length = 0;
  604.       rxlength = MSG_DATA_SIZE-2;
  605.       RxBitOffset = 0;
  606.       iSquelchCount = 0;
  607.       
  608.       PreambleCount = 0;
  609.       RSSISampleFreq = 0;
  610.       RxShiftBuf.W = 0;
  611.       iRSSIcount = 0;
  612.       bTxPending = FALSE;
  613.       bTxBusy = FALSE;
  614.       bRSSIValid = FALSE;
  615.       bAckEnable = FALSE; // to test for ECN only
  616.       bCCAEnable = TRUE;
  617.       CC1K_PulseLevel = 300;
  618.       sMacDelay = -1;
  619.       usRSSIVal = -1;
  620.       usSquelchIndex = 0;
  621.       pulse_check_count = 0;
  622.       lplpower =  0;//0x87;
  623.       RSSIInitState = NULL_STATE;
  624.       //      if(TOS_LOCAL_ADDRESS == 0) lplpower = 0;
  625.       //      lplpowertx = 7;
  626.       usSquelchVal = CC1K_SquelchInit;
  627.       currentMAC = BMAC;
  628.       congBackOffs = 0;
  629.       packetsSent = 0;
  630.       pktsLastSync = 0;
  631.       avgLoss = 0.0;
  632.       curHCLlist = 0;
  633.       globalFrameLength = GLOBAL_FRAME_LENGTH;
  634.       localFrameLength = GLOBAL_FRAME_LENGTH;
  635.       slotSize = 50;
  636.       localFrameSize = localFrameLength * slotSize;
  637.       globalFrameSize = globalFrameLength * slotSize;
  638.       ackOrig = bAckEnable;
  639.       ecnPending = FALSE;
  640.       ecnforward = FALSE;
  641.       enableHCL = FALSE; // ecn flag, set if currently ecn is going on ...
  642.       pureHCL = FALSE;
  643.       HCLselect = SELECTHCL;
  644.       needTimeSync = FALSE;
  645.       slots_since_ecnsend = 0;
  646.       slots_since_ecnrecv = 0;
  647.       slots_since_ecncheck = 0;
  648.       ecnMsgHdr.type = ECNTYPE;  //set ecnMsg headers
  649.       ecnMsgHdr.addr = TOS_BCAST_ADDR; //ECN Indicator;
  650.       ecnMsgHdr.length = sizeof(ecnMsgType);
  651.       ecnMsgHdr.group = 125;
  652.       ecnMsgHdr.crc = 0;
  653.       ecnForwardMsgHdr.type = ECNTYPE;
  654.       ecnForwardMsgHdr.addr = TOS_BCAST_ADDR; 
  655.       ecnForwardMsgHdr.length = sizeof(ecnMsgType);
  656.       ecnForwardMsgHdr.group = 125;
  657.       ecnForwardMsgHdr.crc = 0;
  658.       syncMsgHdr.type = SYNCTYPE;  //set syncMsg headers
  659.       syncMsgHdr.addr = TOS_BCAST_ADDR; //SYNC Indicator;
  660.       syncMsgHdr.length = sizeof(syncMsgType);
  661.       syncMsgHdr.group = 125;
  662.       syncMsgHdr.crc = 0;
  663.       
  664.       ecnMsgPtr->hopCount = 0; //hopcount
  665.       ecnMsgPtr->nextHop = nextHop; //parent node
  666.       ecnMsgPtr->senderAddress = TOS_LOCAL_ADDRESS;
  667.     }
  668.     for (i = 0; i < CC1K_SquelchTableSize; i++)
  669.       usSquelchTable[(int)i] = CC1K_SquelchInit;
  670.     call SpiByteFifo.initSlave(); // set spi bus to slave mode
  671.    
  672.     call CC1000StdControl.init();
  673.     call CC1000Control.SelectLock(0x9); // Select MANCHESTER VIOLATION
  674.     bInvertRxData = call CC1000Control.GetLOStatus();
  675.     call ADCControl.bindPort(TOS_ADC_CC_RSSI_PORT,TOSH_ACTUAL_CC_RSSI_PORT);
  676.     call ADCControl.init();
  677.     
  678.     call Random.init();
  679.     call TimerControl.init();
  680. #ifdef ZMAC_DEBUG
  681.     init_debug();
  682. #endif
  683.     LocalAddr = TOS_LOCAL_ADDRESS;
  684.     return SUCCESS;
  685.   }
  686.   
  687.   /**
  688.    * Get the current Low Power Listening transmit mode
  689.    * @return mode number (see SetListeningMode)
  690.    */
  691.   async command uint8_t LowPowerListening.GetTransmitMode() {
  692.     return lplpowertx;
  693.   }
  694.   // legacy support
  695.   async command uint8_t GetTransmitMode() {
  696.     return call LowPowerListening.GetTransmitMode();
  697.   }
  698.   /**
  699.    * Set the transmit mode.  This allows for hybrid schemes where
  700.    * the transmit mode is different than the receive mode.
  701.    * Use SetListeningMode first, then change the mode with SetTransmitMode.
  702.    *
  703.    * @param mode mode number (see SetListeningMode)
  704.    * @return SUCCESS if the mode was successfully changed
  705.    */
  706.   async command result_t LowPowerListening.SetTransmitMode(uint8_t power) {
  707.     if ((power >= CC1K_LPL_STATES) || (power == lplpowertx))
  708.       return FAIL;
  709.     // check if the radio is currently doing something
  710.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  711.                           (RadioState == IDLE_STATE) ||
  712.                           (RadioState == DISABLED_STATE))) {
  713.       atomic {
  714.         lplpowertx = power;
  715.         preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8)
  716.                        | PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  717.       }
  718.       return SUCCESS;
  719.     }
  720.     return FAIL;
  721.   }
  722.   // legacy support
  723.   async command result_t SetTransmitMode(uint8_t power) {
  724.     return call LowPowerListening.SetTransmitMode(power);
  725.   }
  726.   /**
  727.    * Set the current Low Power Listening mode.
  728.    * Setting the LPL mode sets both the check interval and preamble length.
  729.    *
  730.    * Modes include:
  731.    *  0 = Radio full on
  732.    *  1 = 10ms check interval
  733.    *  2 = 25ms check interval
  734.    *  3 = 50ms check interval
  735.    *  4 = 100ms check interval (recommended)
  736.    *  5 = 200ms check interval
  737.    *  6 = 400ms check interval
  738.    *  7 = 800ms check interval
  739.    *  8 = 1600ms check interval
  740.    *
  741.    * @param mode the mode number
  742.    * @return SUCCESS if the mode was successfully changed
  743.    */
  744.   async command result_t LowPowerListening.SetListeningMode(uint8_t power) {
  745.     // valid low power listening values are 0 to 8
  746.     // 0 is "always on" and 8 is lowest duty cycle
  747.     if ((power >= CC1K_LPL_STATES) || (power == lplpower))
  748.       return FAIL;
  749.     // check if the radio is currently doing something
  750.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  751.                           (RadioState == IDLE_STATE) ||
  752.                           (RadioState == DISABLED_STATE))) {
  753.       // change receiving function in CC1000Radio
  754.       call WakeupTimer.stop();
  755.       atomic {
  756.         if (lplpower == lplpowertx) {
  757.           lplpowertx = power;
  758.         }
  759.         lplpower = power;
  760.       }
  761.       // if successful, change power here
  762.       if (RadioState == IDLE_STATE) {
  763.         RadioState = DISABLED_STATE;
  764.         call StdControl.stop();
  765.         call StdControl.start();
  766.       }
  767.       if (RadioState == POWER_DOWN_STATE) {
  768.         RadioState = DISABLED_STATE;
  769.         call StdControl.start();
  770.         call PowerManagement.adjustPower();
  771.       }
  772.     }
  773.     else {
  774.       return FAIL;
  775.     }
  776.     return SUCCESS;
  777.   }
  778.   // legacy support
  779.   async command result_t SetListeningMode(uint8_t power) {
  780.     return call SetListeningMode(power);
  781.   }
  782.   /**
  783.    * Gets the state of low power listening on the chipcon radio.
  784.    * @return Current low power listening state value
  785.    */
  786.   async command uint8_t LowPowerListening.GetListeningMode() {
  787.     return lplpower;
  788.   }
  789.   // legacy support
  790.   async command uint8_t GetListeningMode() {
  791.     return call LowPowerListening.GetListeningMode();
  792.   } 
  793.   /**
  794.    * Set the preamble length of outgoing packets
  795.    *
  796.    * @param bytes length of the preamble in bytes
  797.    * @return SUCCESS if the preamble length was successfully changed
  798.    */
  799.   async command result_t LowPowerListening.SetPreambleLength(uint16_t bytes) {
  800.     result_t result = FAIL;
  801.     atomic {
  802.       if (RadioState != TX_STATE) {
  803.         preamblelen = bytes;
  804.         result = SUCCESS;
  805.       }
  806.     }
  807.     return result;
  808.   }
  809.   /**
  810.    * Get the preamble length of outgoing packets
  811.    *
  812.    * @return length of the preamble in bytes
  813.    */
  814.   async command uint16_t LowPowerListening.GetPreambleLength() {
  815.     return preamblelen;
  816.   }
  817.   /**
  818.    * Set the check interval (time between waking up and sampling
  819.    * the radio for activity in low power listening)
  820.    *
  821.    * @param ms check interval in milliseconds
  822.    * @return SUCCESS if the check interval was successfully changed
  823.    */
  824.   async command result_t LowPowerListening.SetCheckInterval(uint16_t ms) {
  825.     // sleep time will go into effect after the next wakeup time
  826.     atomic sleeptime = ms;
  827.     return SUCCESS;
  828.   }
  829.   /**
  830.    * Get the check interval currently used by low power listening
  831.    *
  832.    * @return length of the check interval in milliseconds
  833.    */
  834.   async command uint16_t LowPowerListening.GetCheckInterval() {
  835.     return sleeptime;
  836.   }
  837.   event result_t SquelchTimer.fired() {
  838.     char currentRadioState;
  839.     atomic currentRadioState = RadioState;
  840.     if (currentRadioState == IDLE_STATE) {
  841.       atomic RSSIInitState = currentRadioState;
  842.       call RSSIADC.getData();
  843.     }
  844.     return SUCCESS;
  845.   }
  846.   event result_t WakeupTimer.fired() {
  847.     uint8_t currentRadioState;
  848.     if (lplpower == 0)
  849.       return SUCCESS;
  850.     
  851.     atomic currentRadioState = RadioState;
  852.     switch(currentRadioState) {
  853.     case IDLE_STATE:
  854.       if (!bTxPending) {
  855.         atomic {
  856.           RadioState = POWER_DOWN_STATE;
  857.           call SpiByteFifo.disableIntr();
  858.         }
  859.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  860.         call SquelchTimer.stop();
  861.         call CC1000StdControl.stop();
  862.       } else {
  863.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  864.       }
  865.       break;
  866.     case POWER_DOWN_STATE:
  867.       atomic RadioState = PULSE_CHECK_STATE;
  868.       pulse_check_count = 0;
  869.       call CC1000StdControl.start();
  870.       call CC1000Control.BIASOn();
  871.       call WakeupTimer.start(TIMER_ONE_SHOT, 1);
  872.       return SUCCESS;
  873.       break;
  874.     case PULSE_CHECK_STATE:
  875.       call CC1000Control.RxMode();
  876.       if(!(call RSSIADC.getData())){
  877.         call WakeupTimer.start(TIMER_ONE_SHOT, TIME_BETWEEN_CHECKS);
  878.         atomic RadioState = POWER_DOWN_STATE;
  879.       }
  880.       else {
  881.         TOSH_uwait(80);
  882.       }
  883.       call CC1000StdControl.stop();
  884.       pulse_check_sum ++;
  885.       break;
  886.     default:
  887.       call WakeupTimer.start(TIMER_ONE_SHOT, 5);
  888.     }
  889.     return SUCCESS;
  890.   }
  891.   //added by Mahesh
  892.   event result_t TDMATimer.fired(){
  893.     call TDMATimer.start(TIMER_ONE_SHOT, slotMultiplier);
  894.     slotNum++;
  895.     atomic currentMAC = ZMAC;
  896.     atomic{
  897.       currentSlot = slotNum & (localFrameLength - 1);
  898.       globalSlot = slotNum & (globalFrameLength - 1);
  899. #ifdef ZMAC_TIMER
  900.       SODbg(DBG_USR2,"*************Timer fired with current slot = %u, own slot = %un", currentSlot, ownSlot);
  901. #endif 
  902.       if(HCLselect){
  903.         slots_since_ecnsend ++;
  904.         slots_since_ecnrecv ++;
  905.         slots_since_ecncheck++;
  906.         if((packetsSent > ECNMINPACKETS) && (slots_since_ecncheck >= ECNCHECKPERIOD)){
  907.           double currentLoss = (double)congBackOffs/packetsSent;
  908.           avgLoss = ALPHA * (currentLoss) + (1 - ALPHA) * avgLoss;
  909. #ifdef ZMAC_ECN
  910.           SODbg(DBG_USR2,"#####################Congestion Statistics: %i / %i, %in", congBackOffs, packetsSent, (uint16_t) avgLoss);
  911. #endif
  912.           slots_since_ecncheck = 0;
  913.           congBackOffs = 0;
  914.           packetsSent = 0;
  915.           if((avgLoss > ECNTHRESHOLD) && (slots_since_ecnsend >= ECNSENDPERIOD)){
  916.             ecnMsgType *ecnMsgPtr = (ecnMsgType *) ecnMsgHdr.data;
  917. #ifdef ZMAC_ECN
  918.             SODbg(DBG_USR2,"Setting ECN flagn");
  919. #endif
  920.             // change by acw, go to ecn myself if sending ecn
  921.             atomic enableHCL = TRUE;
  922.             slots_since_ecnrecv = 0;
  923.             // change by acw ends
  924.             ecnMsgPtr->nextHop = nextHop;
  925.             if(!pureHCL)
  926.               ecnPending = TRUE;
  927.           }
  928.         }
  929.         if((enableHCL) && (slots_since_ecnrecv >= ECNEXPIREPERIOD)){
  930.           if(!pureHCL)
  931.             enableHCL = FALSE;
  932. #ifdef ZMAC_ECN
  933.           SODbg(DBG_USR2,"ECN expired, into LCL againn");
  934. #endif
  935.         }
  936.         
  937. #ifdef ZMAC_ECN
  938.         if(enableHCL)
  939.           SODbg(DBG_USR2,"Current slot %i **********************n",currentSlot);
  940. #endif
  941. #ifdef ZMAC_ECN
  942.         if(enableHCL && IsHCL(globalSlot) && ownSlot != currentSlot)
  943.           SODbg(DBG_USR2,"***** ****** ****** ****** Current slot %i HCLn",currentSlot);
  944. #endif
  945.       }
  946.       if(bTxPending){
  947.         sMacDelay = getZMACBackoff(sMacDelay);
  948. #ifdef ZMAC_BACKOFF
  949.         SODbg(DBG_USR2,"TDMATimerFired: backoff %un", sMacDelay);
  950. #endif
  951.       }
  952.     }
  953.     return SUCCESS;
  954.   }
  955.  
  956.   command result_t StdControl.stop() {
  957.     atomic RadioState = DISABLED_STATE;
  958.     call SquelchTimer.stop();
  959.     call WakeupTimer.stop();
  960.     call CC1000StdControl.stop();
  961.     call SpiByteFifo.disableIntr(); // disable spi interrupt
  962.     return SUCCESS;
  963.   }
  964.   command result_t StdControl.start() {
  965.     uint8_t currentRadioState;
  966.     atomic currentRadioState = RadioState;
  967.     call SClock.SetRate(MAX_VAL,CLK_DIV_64);
  968.     if (currentRadioState == DISABLED_STATE) {
  969.       atomic {
  970.         rxbufptr->length = 0;
  971.         RadioState  = IDLE_STATE;
  972.         bTxPending = bTxBusy = FALSE;
  973.         sMacDelay = -1;
  974.         if(SLEEPTIME > 0){
  975.           sleeptime = SLEEPTIME;
  976.           preamblelen = PREAMBLELEN;
  977.         } else{
  978.           lplpower = lplpowertx = 0;
  979.           sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) |
  980.                        PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1]));
  981.           preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) |
  982.                          PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  983.         }
  984. /*         sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) | */
  985. /*                      PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1])); */
  986. /*         preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) | */
  987. /*                        PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1])); */
  988.       }
  989.       // all power on, captain!
  990.       rxbufptr->length = 0;
  991.       atomic RadioState = IDLE_STATE;
  992.       call CC1000StdControl.start();
  993.       call CC1000Control.BIASOn();
  994.       call SpiByteFifo.rxMode(); // SPI to miso
  995.       call CC1000Control.RxMode();
  996.       if (iSquelchCount > CC1K_SquelchCount)
  997.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  998.       else
  999.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  1000.       call SpiByteFifo.enableIntr(); // enable spi interrupt
  1001.       if (lplpower > 0) {
  1002.         // set a time to start sleeping after measuring the noise floor
  1003.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_SquelchIntervalSlow);
  1004.       }
  1005.     }
  1006.     return SUCCESS;
  1007.   }
  1008.   command result_t Send.send(TOS_MsgPtr pMsg) {
  1009.     result_t Result = SUCCESS;
  1010.     uint8_t currentRadioState = 0;
  1011.    
  1012.     atomic {
  1013.       if (bTxBusy) {
  1014.         Result = FAIL;
  1015. #ifdef ZMAC_DEBUG
  1016.         //        SODbg(DBG_USR2, "Busy sending the message of type %u!n", txbufptr->type);
  1017. #endif
  1018.       } else {
  1019.         bTxBusy = TRUE;
  1020.         txbufptr = pMsg;
  1021.         txlength = pMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
  1022.         if(bCCAEnable){ // initially back off [1,32] bytes (approx 2/3 packet)
  1023.           if(currentMAC == BMAC)
  1024.             sMacDelay = signal MacBackoff.initialBackoff(pMsg);
  1025.           else
  1026.             sMacDelay = getZMACBackoff(0);
  1027.         } else
  1028.           sMacDelay = 0;
  1029. #ifdef ZMAC_BACKOFF
  1030.         SODbg(DBG_USR2, "SendMSG(): Need to send type %u, myslot %u, current slot %u backoff %un",
  1031.               txbufptr->type, ownSlot, currentSlot, sMacDelay);
  1032. #endif
  1033.         bTxPending = TRUE;
  1034.       }
  1035.       currentRadioState = RadioState;
  1036.     }
  1037.     if (Result) {
  1038.       if (currentRadioState == POWER_DOWN_STATE) {       // if we're off, start the radio
  1039.         atomic RadioState = IDLE_STATE;         // disable wakeup timer
  1040.         call WakeupTimer.stop();
  1041.         call CC1000StdControl.start();
  1042.         call CC1000Control.BIASOn();
  1043.         call CC1000Control.RxMode();
  1044.         call SpiByteFifo.rxMode(); // SPI to miso
  1045.         call SpiByteFifo.enableIntr(); // enable spi interrupt
  1046.         if (iSquelchCount > CC1K_SquelchCount)
  1047.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  1048.         else
  1049.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  1050.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
  1051.       }
  1052.     }
  1053.     return Result;
  1054.   }
  1055.   
  1056.   /**********************************************************
  1057.    * make a spibus interrupt handler
  1058.    * needs to handle interrupts for transmit delay
  1059.    * and then go into byte transmit mode with
  1060.    *   timer1 baudrate delay as interrupt handler
  1061.    * else SODbg(DBG_USR2,"Sending Packet ..");
  1062.    * needs to handle interrupts for byte read and detect preamble
  1063.    *  then handle reading a packet
  1064.    * PB - We can use this interrupt handler as a transmit scheduler
  1065.    * because the CC1000 continuously clocks in data, regarless
  1066.    * of whether it's good or not.  Thus, this routine will be called
  1067.    * on every 8 ticks of DCLK. 
  1068.    **********************************************************/
  1069.   async event result_t SpiByteFifo.dataReady(uint8_t data_in) {
  1070.     GTime loctime;
  1071.     signal RadioSendCoordinator.blockTimer();
  1072.     signal RadioReceiveCoordinator.blockTimer();
  1073.      
  1074.     if (bInvertRxData)
  1075.       data_in = ~data_in;
  1076. #ifdef ENABLE_UART_DEBUG
  1077.     UARTPutChar(RadioState);
  1078. #endif
  1079.     switch (RadioState) {
  1080.     case TX_STATE:
  1081.       {
  1082.         call SpiByteFifo.writeByte(NextTxByte);
  1083.         TxByteCnt++;
  1084.         switch (RadioTxState) {
  1085.           
  1086.         case TXSTATE_PREAMBLE:
  1087.           send_sum ++;
  1088.           if (!(TxByteCnt < preamblelen)||
  1089.               (txbufptr->strength == 0xffff && TxByteCnt >= PREAMBLE_LENGTH_TO_BASE)) {
  1090.             NextTxByte = SYNC_BYTE;
  1091.             RadioTxState = TXSTATE_SYNC;
  1092. #ifdef ZMAC_ECN
  1093.             SODbg(DBG_USR2,"Sent packet in slot %in",currentSlot);
  1094.             SODbg(DBG_USR2, "ishcl = %un", IsHCL(currentSlot));
  1095. #endif
  1096.           }
  1097.           break;
  1098.         case TXSTATE_SYNC:
  1099.           send_sum ++;
  1100.           NextTxByte = NSYNC_BYTE;
  1101.           RadioTxState = TXSTATE_DATA;
  1102.           TxByteCnt = -1;
  1103.           if(txbufptr->type == SYNCTYPE){ // allow sync messages
  1104.             syncMsgType *syncMsgPtr = (syncMsgType *) txbufptr->data;
  1105.             call SClock.getTime(&loctime);
  1106.             syncMsgPtr->mticks = loctime.mticks;
  1107.             syncMsgPtr->sticks = loctime.sticks;
  1108.             syncMsgPtr->trust = TRUST_FACTOR;
  1109.             syncMsgPtr->sender = TOS_LOCAL_ADDRESS;
  1110.           }
  1111.           // for Time Sync services
  1112.           signal RadioSendCoordinator.startSymbol(8, 0, txbufptr);
  1113.           break;
  1114.         case TXSTATE_DATA:
  1115.           send_sum ++;
  1116.           if ((uint8_t)(TxByteCnt) < txlength){
  1117.             if((txbufptr->type == SYNCTYPE) && (TxByteCnt == 5)){ // 5 = offset of timestamp
  1118.               syncMsgType *syncMsgPtr = (syncMsgType *) txbufptr->data;
  1119.               call SClock.getTime(&loctime);
  1120.               AddTime(&loctime, &loctime, &constOffset);
  1121.               syncMsgPtr->mticks = loctime.mticks;
  1122.               syncMsgPtr->sticks = loctime.sticks;
  1123.             }
  1124.             NextTxByte = ((uint8_t *)txbufptr)[(TxByteCnt)];
  1125.             usRunningCRC = crcByte(usRunningCRC,NextTxByte);
  1126.             signal RadioSendCoordinator.byte(txbufptr, (uint8_t)TxByteCnt); // Time Sync
  1127.           }
  1128.           else {
  1129.             NextTxByte = (uint8_t)(usRunningCRC);
  1130.             RadioTxState = TXSTATE_CRC;
  1131.           }
  1132.           break;
  1133.         case TXSTATE_CRC:
  1134.           send_sum ++;
  1135.           NextTxByte = (uint8_t)(usRunningCRC>>8);
  1136.           RadioTxState = TXSTATE_FLUSH;
  1137.           TxByteCnt = 0;
  1138.           break;
  1139.         case TXSTATE_FLUSH:
  1140.           send_sum ++;
  1141.           if (TxByteCnt > 3) {
  1142.             TxByteCnt = 0;
  1143. #ifdef ZMAC_DEBUG
  1144.             // SODbg(DBG_USR2,"Came heren");
  1145. #endif
  1146.             if (bAckEnable)
  1147.               RadioTxState = TXSTATE_WAIT_FOR_ACK;         
  1148.             else {
  1149. #ifdef ZMAC_DEBUG
  1150.               // SODbg(DBG_USR2,"came inside: current MAC: %i ackenabled :%i,ecnPending: %i ecnforward %i ecnSENT %in",currentMAC,bAckEnable,ecnPending,ecnforward,sentECN);
  1151. #endif
  1152.               packetsSent ++;
  1153.               call SpiByteFifo.rxMode();
  1154.               call CC1000Control.RxMode();
  1155.               RadioTxState = TXSTATE_DONE;
  1156.             }
  1157.           }
  1158.           break;
  1159.         case TXSTATE_WAIT_FOR_ACK:
  1160.           if(TxByteCnt == 1){
  1161.             send_sum ++;
  1162.             call SpiByteFifo.rxMode();
  1163.             call CC1000Control.RxMode();
  1164.             break;
  1165.           }
  1166.           receive_sum ++;
  1167.           if (TxByteCnt > 3) {
  1168.             RadioTxState = TXSTATE_READ_ACK;
  1169.             TxByteCnt = 0;
  1170.             search_word = 0;
  1171.           }
  1172.           break;
  1173.         case TXSTATE_READ_ACK:
  1174.           {
  1175.             uint8_t i;
  1176.             receive_sum ++;
  1177.             for(i = 0; i < 8; i ++){
  1178.               search_word <<= 1;
  1179.               if(data_in & 0x80) search_word |=  0x1;
  1180.               data_in <<= 1;
  1181.               if (search_word == 0xba83){
  1182.                 txbufptr->ack = 1;
  1183.                 RadioTxState = TXSTATE_DONE;
  1184. #ifdef ZMAC_DEBUG
  1185.                 //                SODbg(DBG_USR2,"received ackn");
  1186. #endif
  1187.                 return SUCCESS;
  1188.               }
  1189.             }
  1190.           }
  1191.           if(TxByteCnt >= MAX_ACK_WAIT){   
  1192.             txbufptr->ack = 0;  
  1193. #ifdef ZMAC_DEBUG
  1194.             //       SODbg(DBG_USR2,"did not receive ack %i %i %in",lostacks,packetsSent,avgLoss * 100);
  1195. #endif
  1196.             RadioTxState = TXSTATE_DONE;
  1197.           }
  1198.           break;
  1199.         case TXSTATE_DONE:
  1200.         default:
  1201.           bTxPending = FALSE;
  1202.           if((txbufptr->type == ECNTYPE) || (txbufptr->type == SYNCTYPE)){
  1203. #ifdef ZMAC_ECN
  1204.             ecnForwardMsgType *ecnForwardMsgPtr = (ecnForwardMsgType *) txbufptr->data;
  1205.             if(txbufptr->type == ECNTYPE && ecnForwardMsgPtr->hopCount == 1)
  1206.               SODbg(DBG_USR2,"Successfully forwarded ECNn");
  1207. #endif
  1208.             bAckEnable = ackOrig;
  1209.           }
  1210. #ifdef ZMAC_BACKOFF
  1211.           SODbg(DBG_USR2, "Sent one packet of type %u, myslot %u, current slot %u!n", txbufptr->type,
  1212.                 ownSlot, currentSlot);
  1213. #endif
  1214.           if(post PacketSent()) {
  1215.             // If the post operation succeeds, goto Idle
  1216.             // otherwise, we'll try again.
  1217. #ifdef ZMAC_DEBUG
  1218.             //  SODbg(DBG_USR2,"Packet type %in",txbufptr->type);
  1219. #endif
  1220.             RadioState = IDLE_STATE;
  1221.             pktsLastSync++;
  1222.             RSSIInitState = RadioState;
  1223.             call RSSIADC.getData();
  1224.           }
  1225.           break;
  1226.         }
  1227.       }
  1228.       break;
  1229.     case DISABLED_STATE:
  1230.       break;
  1231.     case IDLE_STATE: 
  1232.       {
  1233.         receive_sum ++;
  1234.         if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  1235.           PreambleCount++;
  1236.           if (PreambleCount > CC1K_ValidPrecursor) {
  1237.             PreambleCount = SOFCount = 0;
  1238.             RxBitOffset = RxByteCnt = 0;
  1239.             usRunningCRC = 0;
  1240.             rxlength = MSG_DATA_SIZE-2;
  1241.             RadioState = SYNC_STATE;
  1242.           }
  1243.         } else {
  1244.           if ((currentMAC == BMAC) || (enableHCL == FALSE) || (!IsHCL(currentSlot))) {
  1245.             if((bTxPending) && (--sMacDelay <= 0)){
  1246.               RadioState = PRETX_STATE;
  1247.               RSSIInitState = PRETX_STATE;
  1248.               bRSSIValid = FALSE;
  1249.               iRSSIcount = 0;
  1250.               PreambleCount = 0;
  1251.               call RSSIADC.getData();
  1252.             }
  1253.           } else{
  1254. #ifdef ZMAC_ECN
  1255.             SODbg(DBG_USR2, "&&&&&&&&&&&&&&&&&&&&& ishcl = %un", IsHCL(currentSlot));
  1256. #endif
  1257.           }
  1258.         }
  1259.       }
  1260.       break;
  1261.     case PRETX_STATE:
  1262.       {
  1263.         receive_sum ++;
  1264.         if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  1265.           // Back to the penalty box.
  1266.           sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
  1267. #ifdef ZMAC_BACKOFF
  1268.           SODbg(DBG_USR2,"SpiDataReady: detected preamble - backoff %un", sMacDelay);
  1269. #endif
  1270.           RadioState = IDLE_STATE;
  1271.         }
  1272.       }
  1273.       break;
  1274.     case SYNC_STATE:
  1275.       {
  1276.         // draw in the preamble bytes and look for a sync byte
  1277.         // save the data in a short with last byte received as msbyte
  1278.         //    and current byte received as the lsbyte.
  1279.         // use a bit shift compare to find the byte boundary for the sync byte
  1280.         // retain the shift value and use it to collect all of the packet data
  1281.         // check for data inversion, and restore proper polarity 
  1282.         // XXX-PB: Don't do this.
  1283.         uint8_t i;
  1284.         receive_sum ++;
  1285.         if ((data_in == 0xaa) || (data_in == 0x55)) {
  1286.           // It is actually possible to have the LAST BIT of the incoming
  1287.           // data be part of the Sync Byte.  SO, we need to store that
  1288.           // However, the next byte should definitely not have this pattern.
  1289.           // XXX-PB: Do we need to check for excessive preamble?
  1290.           RxShiftBuf.MSB = data_in;
  1291.         }
  1292.         else {
  1293.           // TODO: Modify to be tolerant of bad bits in the preamble...
  1294.           uint16_t usTmp;
  1295.           switch (SOFCount) {
  1296.           case 0:
  1297.             RxShiftBuf.LSB = data_in;
  1298.             break;
  1299.   
  1300.           case 1:
  1301.           case 2: 
  1302.           case 3: 
  1303.           case 4: 
  1304.           case 5: 
  1305.             // bit shift the data in with previous sample to find sync
  1306.             usTmp = RxShiftBuf.W;
  1307.             RxShiftBuf.W <<= 8;
  1308.             RxShiftBuf.LSB = data_in;
  1309.             for(i=0;i<8;i++) {
  1310.               usTmp <<= 1;
  1311.               if(data_in & 0x80)
  1312.                 usTmp  |=  0x1;
  1313.               data_in <<= 1;
  1314.               // check for sync bytes
  1315.               if (usTmp == SYNC_WORD) {
  1316.                 if (rxbufptr->length !=0) {
  1317.                   call Leds.redToggle();
  1318.                   RadioState = IDLE_STATE;
  1319.                 }
  1320.                 else {
  1321.                   RadioState = RX_STATE;
  1322.                   RSSIInitState = RX_STATE;
  1323.                   call RSSIADC.getData();
  1324.                   RxBitOffset = 7-i;
  1325.                   // For time sync services
  1326.                   signal RadioReceiveCoordinator.startSymbol(8, RxBitOffset, rxbufptr); 
  1327.                 }
  1328.                 break;
  1329.               }
  1330.             }
  1331.             break;
  1332.           default:
  1333.             // We didn't find it after a reasonable number of tries, so....
  1334.             RadioState = IDLE_STATE;  // Ensures we wait till the end of the transmission
  1335.             break;
  1336.           }
  1337.           SOFCount++;
  1338.         }
  1339.       }
  1340.       break;
  1341.       //  collect the data and shift into double buffer
  1342.       //  shift out data by correct offset
  1343.       //  invert the data if necessary
  1344.       //  stop after the correct packet length is read
  1345.       //  return notification to upper levels
  1346.       //  go back to idle state
  1347.     case RX_STATE:
  1348.       {
  1349.         char Byte;
  1350.         receive_sum ++;
  1351.         RxShiftBuf.W <<=8;
  1352.         RxShiftBuf.LSB = data_in;
  1353.         Byte = (RxShiftBuf.W >> RxBitOffset);
  1354.         ((char*)rxbufptr)[(int)RxByteCnt] = Byte;
  1355.         RxByteCnt++;
  1356.         signal RadioReceiveCoordinator.byte(rxbufptr, (uint8_t)RxByteCnt);
  1357.         if (RxByteCnt < rxlength) {
  1358.           usRunningCRC = crcByte(usRunningCRC,Byte);
  1359.           if (RxByteCnt == (offsetof(struct TOS_Msg,length) + 
  1360.                             sizeof(((struct TOS_Msg *)0)->length))) {
  1361.             rxlength = rxbufptr->length;
  1362.             if (rxlength > TOSH_DATA_LENGTH) {
  1363.               // The packet's screwed up, so just dump it
  1364.               rxbufptr->length = 0;
  1365.               RadioState = IDLE_STATE;  // Waits till end of transmission
  1366.               return SUCCESS;
  1367.             }
  1368.             //Add in the header size
  1369.             rxlength += offsetof(struct TOS_Msg,data);
  1370.           }
  1371.         }
  1372.         else if (RxByteCnt == rxlength) {
  1373.           if(rxbufptr->type == SYNCTYPE) // got all bytes of time stamp !
  1374.             getTimeDiff();
  1375.           usRunningCRC = crcByte(usRunningCRC,Byte);
  1376.           // Shift index ahead to the crc field.
  1377.           RxByteCnt = offsetof(struct TOS_Msg,crc);
  1378.         }
  1379.         else if (RxByteCnt >= MSG_DATA_SIZE) { 
  1380.           // Packet filtering based on bad CRC's is done at higher layers.
  1381.           // So sayeth the TOS weenies.
  1382.           if (rxbufptr->crc == usRunningCRC) {
  1383.             if(rxbufptr->type == SYNCTYPE)
  1384.               post adjustTime();
  1385.             rxbufptr->crc = 1;
  1386.             
  1387.             if(bAckEnable && (rxbufptr->addr == TOS_LOCAL_ADDRESS)){
  1388.               RadioState = SENDING_ACK; 
  1389.               call CC1000Control.TxMode();
  1390.               call SpiByteFifo.txMode();
  1391.               call SpiByteFifo.writeByte(0xaa);
  1392.               RxByteCnt = 0;
  1393.               return SUCCESS; 
  1394.             }
  1395.           } else {
  1396.             rxbufptr->crc = 0;
  1397.           }
  1398.           call SpiByteFifo.disableIntr();
  1399.   
  1400.           RadioState = IDLE_STATE; //DISABLED_STATE;
  1401.           if((currentMAC == ZMAC) && (bTxPending)){ //Ajit - reset timer when time slot boundary
  1402.             sMacDelay = getZMACBackoff(sMacDelay);
  1403. #ifdef ZMAC_BACKOFF
  1404.             SODbg(DBG_USR2,"JustAfterReceive: backoff %u mySlot %u currentSlot %un", sMacDelay,
  1405.                   ownSlot, currentSlot);
  1406. #endif
  1407.           }
  1408.           rxbufptr->strength = usRSSIVal;
  1409.           if (!(post PacketRcvd())) {
  1410.             // If there are insufficient resources to process the incoming packet
  1411.             // we drop it
  1412.             rxbufptr->length = 0;
  1413.             RadioState = IDLE_STATE;
  1414.             call SpiByteFifo.enableIntr();
  1415.           }
  1416.           RSSIInitState = RadioState;
  1417.           call RSSIADC.getData();
  1418.         }
  1419.       }
  1420.       break;
  1421.     case SENDING_ACK:
  1422.       {
  1423.         send_sum ++;
  1424.         RxByteCnt++;
  1425.         if (RxByteCnt >= ACK_LENGTH) { 
  1426.           call CC1000Control.RxMode();
  1427.           call SpiByteFifo.rxMode();
  1428.           call SpiByteFifo.disableIntr();
  1429.           RadioState = IDLE_STATE; //DISABLED_STATE;
  1430.           rxbufptr->strength = usRSSIVal;
  1431.           if (!(post PacketRcvd())) {
  1432.             rxbufptr->length = 0;
  1433.             RadioState = IDLE_STATE;
  1434.             call SpiByteFifo.enableIntr();
  1435.           }
  1436.         }else if(RxByteCnt >= ACK_LENGTH - sizeof(ack_code)){
  1437.           call SpiByteFifo.writeByte(ack_code[RxByteCnt + sizeof(ack_code) - ACK_LENGTH]);
  1438.         }
  1439.       }
  1440.       break;
  1441.     default:
  1442.       break;
  1443.     }
  1444.     if(pulse_check_sum > CHECK_MA_COUNT){
  1445.       power_sum ++;
  1446.       sp_sum++;
  1447.       pulse_check_sum -= CHECK_MA_COUNT;
  1448.     }
  1449.     if(send_sum > SEND_MA_COUNT){
  1450.       power_sum ++;
  1451.       tx_sum++;
  1452.       send_sum -= SEND_MA_COUNT;
  1453.     }
  1454.     if(receive_sum > RECEIVE_MA_COUNT){
  1455.       power_sum ++;
  1456.       rx_sum++;
  1457.       receive_sum -= RECEIVE_MA_COUNT;
  1458.     }
  1459.     return SUCCESS;
  1460.   }
  1461.   task void IdleTimerTask(){
  1462.     if (iSquelchCount > CC1K_SquelchCount)
  1463.       call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  1464.     else
  1465.       call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  1466.     call WakeupTimer.start(TIMER_ONE_SHOT, TIME_AFTER_CHECK);
  1467.     /*if(pulse_check_sum > CHECK_MA_COUNT){
  1468.       power_sum ++;
  1469.       pulse_check_sum -= CHECK_MA_COUNT;
  1470.       }
  1471.       if(send_sum > SEND_MA_COUNT){
  1472.       power_sum ++;
  1473.       send_sum -= SEND_MA_COUNT;
  1474.       }
  1475.       if(receive_sum > RECEIVE_MA_COUNT){
  1476.       power_sum ++;
  1477.       receive_sum -= RECEIVE_MA_COUNT;
  1478.       }*/
  1479.   }
  1480.   task void SleepTimerTask(){
  1481.     call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  1482.   }
  1483.   async event result_t RSSIADC.dataReady(uint16_t data) { 
  1484.     atomic{
  1485.       uint8_t currentRadioState;
  1486.       // TOSH_CLR_PW3_PIN();
  1487.       currentRadioState = RadioState;
  1488.       // find the maximum RSSI value over CC1K_MAX_RSSI_SAMPLES
  1489.       switch(currentRadioState) {
  1490.       case IDLE_STATE:
  1491.         if (RSSIInitState == IDLE_STATE) {
  1492.           atomic usTempSquelch = data;
  1493.           post adjustSquelch();
  1494.         }
  1495.         RSSIInitState = NULL_STATE;
  1496.         break;
  1497.           
  1498.       case RX_STATE:
  1499.         if (RSSIInitState == RX_STATE) {
  1500.           atomic usRSSIVal = data;
  1501.         }
  1502.         RSSIInitState = NULL_STATE;
  1503.         break;
  1504.         
  1505.       case PRETX_STATE:
  1506.         iRSSIcount++;
  1507.         
  1508.         // if the channel is clear or CCA is disabled, GO GO GO!
  1509.         if (((data > (usSquelchVal + CC1K_SquelchBuffer)) ||
  1510.              (!bCCAEnable)) && (RSSIInitState == PRETX_STATE)) { 
  1511.           call SpiByteFifo.writeByte(0xaa);
  1512.           call CC1000Control.TxMode();
  1513.           call SpiByteFifo.txMode();
  1514.           
  1515.           usRSSIVal = data;
  1516.           iRSSIcount = CC1K_MaxRSSISamples;
  1517.           bRSSIValid = TRUE;
  1518.           TxByteCnt = 0;
  1519.           usRunningCRC = 0;
  1520.           RadioState = TX_STATE;
  1521.           RadioTxState = TXSTATE_PREAMBLE;
  1522.           NextTxByte = 0xaa;
  1523.           RSSIInitState = NULL_STATE;
  1524.         }
  1525.         else {
  1526.           RSSIInitState = NULL_STATE;
  1527.           if (iRSSIcount == CC1K_MaxRSSISamples) {
  1528.             sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
  1529. #ifdef ZMAC_BACKOFF
  1530.             SODbg(DBG_USR2,"adcDataReady: channel busy, backoff %un", sMacDelay);
  1531. #endif
  1532.             RadioState = IDLE_STATE;
  1533.           }
  1534.           else {
  1535.             RSSIInitState = currentRadioState;
  1536.             call RSSIADC.getData();
  1537.           }
  1538.         }
  1539.         break;
  1540.         
  1541.       case PULSE_CHECK_STATE:
  1542.         atomic{
  1543.           uint8_t done = 0;
  1544.           uint16_t threshold = call GetSquelch();
  1545.           threshold = threshold - (call GetSquelch() >> 2);
  1546.           if(data > threshold){
  1547.             // adjust the noise floor level
  1548.             atomic usTempSquelch = data;
  1549.             post adjustSquelch();
  1550.             
  1551.           }else if(pulse_check_count > 5){
  1552.             //go to the idle state since no outliers were found
  1553.             call CC1000Control.RxMode();
  1554.             RadioState = IDLE_STATE;
  1555.             call SpiByteFifo.rxMode();     // SPI to miso
  1556.             call SpiByteFifo.enableIntr(); // enable spi interrupt
  1557.             post IdleTimerTask();
  1558.             done = 1;
  1559.             
  1560.           }else {
  1561.             call CC1000Control.RxMode();
  1562.             if(call RSSIADC.getData()){
  1563.               TOSH_uwait(80);
  1564.               pulse_check_count ++;
  1565.               done = 1;
  1566.             }
  1567.             pulse_check_sum ++;
  1568.             call CC1000StdControl.stop();
  1569.           }
  1570.             
  1571.           if (bTxPending) { // bug fixed by Dr. Rhee
  1572.             //go to the idle state since no outliers were found
  1573.             call CC1000Control.RxMode();
  1574.             RadioState = IDLE_STATE;
  1575.             call SpiByteFifo.rxMode();     // SPI to miso
  1576.             call SpiByteFifo.enableIntr(); // enable spi interrupt
  1577.             post IdleTimerTask();
  1578.             done = 1;
  1579.           }
  1580.           if(done == 0){
  1581.             post SleepTimerTask();
  1582.             RadioState = POWER_DOWN_STATE;
  1583.             call SpiByteFifo.disableIntr();
  1584.           }
  1585.         }
  1586.         //go to the power down state
  1587.         break;
  1588.       default:
  1589.       }
  1590.     }
  1591.     return SUCCESS;
  1592.   }
  1593.   // XXX:JP- for testing the mac layer squlech value
  1594.   async command uint16_t GetSquelch() {
  1595.     return usSquelchVal;
  1596.   }
  1597.   // XXX:JP- for testing the mac layer power consumption
  1598.   async command uint16_t GetPower() {
  1599.     return power_sum;
  1600.   }
  1601.   async command uint16_t GetDataSent() {
  1602.     return dataSent;
  1603.   }
  1604.   async command result_t ResetDataSent() {
  1605.     dataSent = 0;
  1606.     return SUCCESS;
  1607.   }
  1608.   async command uint16_t GetPower_tx() {
  1609.     return tx_sum;
  1610.   }
  1611.   async command uint16_t GetPower_rx() {
  1612.     return rx_sum;
  1613.   }
  1614.   async command uint16_t GetPower_sp() {
  1615.     return sp_sum;
  1616.   }
  1617.   async command result_t ResetPower() {
  1618.     power_sum = 0;
  1619.     pulse_check_sum = 0;
  1620.     send_sum = 0;
  1621.     receive_sum = 0;
  1622.     sp_sum = 0;
  1623.     tx_sum = 0;
  1624.     rx_sum = 0;
  1625.     return SUCCESS;
  1626.   }
  1627.   async command result_t MacControl.enableAck() {
  1628.     atomic bAckEnable = TRUE;
  1629.     return SUCCESS;
  1630.   }
  1631.   async command result_t MacControl.disableAck() {
  1632.     atomic bAckEnable = FALSE;
  1633.     return SUCCESS;
  1634.   }
  1635.   async command result_t MacControl.enableCCA() {
  1636.     atomic bCCAEnable = TRUE;
  1637.     return SUCCESS;
  1638.   }
  1639.   async command result_t MacControl.disableCCA() {
  1640.     atomic bCCAEnable = FALSE; 
  1641.     return SUCCESS;
  1642.   }
  1643.   // ***Not yet implemented
  1644.   async command TOS_MsgPtr MacControl.HaltTx() {
  1645.     return 0;
  1646.   }
  1647.   // Default events for radio send/receive coordinators do nothing.
  1648.   // Be very careful using these, you'll break the stack.
  1649.   default async event void RadioSendCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset,
  1650.                                                             TOS_MsgPtr msgBuff) { }
  1651.   default async event void RadioSendCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  1652.   default async event void RadioSendCoordinator.blockTimer() { }
  1653.   default async event void RadioReceiveCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset,
  1654.                                                                TOS_MsgPtr msgBuff) { }
  1655.   default async event void RadioReceiveCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  1656.   default async event void RadioReceiveCoordinator.blockTimer() { }
  1657.   default async event int16_t MacBackoff.initialBackoff(TOS_MsgPtr m){
  1658.     return (call Random.rand() & 0x1F) + 1;
  1659.   }
  1660.   default async event int16_t MacBackoff.congestionBackoff(TOS_MsgPtr m){
  1661.     congBackOffs++;
  1662.     return (call Random.rand() & 0xF) + 1;
  1663.   }
  1664.   /**************SClock Interface********/
  1665.   async event result_t SClock.syncDone(){
  1666.     if(needTimeSync){
  1667.       GTime loctime;
  1668.       uint32_t globalTimeStamp, slotOffset;
  1669.       call SClock.getTime(&loctime);
  1670.       globalTimeStamp = (uint32_t)(loctime.mticks * 568.889 + loctime.sticks * 0.00868056); //in ms
  1671.       slotOffset = (uint32_t) (1.024 * (slotSize - (globalTimeStamp % slotSize))); // in timer units .976562 = 1000/1024
  1672.       slotNum = (uint32_t) (globalTimeStamp/slotSize);
  1673.       currentSlot = slotNum & (localFrameLength - 1);
  1674.       globalSlot = slotNum & (globalFrameLength - 1);
  1675.       if(currentMAC == ZMAC)
  1676.         call TDMATimer.start(TIMER_ONE_SHOT, slotOffset);
  1677.       needTimeSync = FALSE;
  1678.     }
  1679.     return SUCCESS;
  1680.   }
  1681.   async event result_t SClock.fire(uint16_t mticks){ return SUCCESS; }  
  1682. }