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

网络

开发平台:

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