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

网络

开发平台:

Others

  1. // $Id: CC1000RadioIntM.nc,v 1.6 2005/08/16 19:18:47 acwarrie Exp $
  2. /* -*- Mode: C; c-basic-indent: 2; indent-tabs-mode: nil -*- */ 
  3. /* tab:4
  4.  *
  5.  *
  6.  * "Copyright (c) 2000-2002 The Regents of the University  of California.  
  7.  * All rights reserved.
  8.  *
  9.  * Permission to use, copy, modify, and distribute this software and its
  10.  * documentation for any purpose, without fee, and without written agreement is
  11.  * hereby granted, provided that the above copyright notice, the following
  12.  * two paragraphs and the author appear in all copies of this software.
  13.  * 
  14.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  15.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  16.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  17.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  18.  * 
  19.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  20.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  21.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  22.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  23.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
  24.  *
  25.  */
  26. /* tab:4
  27.  *  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.  By
  28.  *  downloading, copying, installing or using the software you agree to
  29.  *  this license.  If you do not agree to this license, do not download,
  30.  *  install, copy or use the software.
  31.  *
  32.  *  Intel Open Source License 
  33.  *
  34.  *  Copyright (c) 2002 Intel Corporation 
  35.  *  All rights reserved. 
  36.  *  Redistribution and use in source and binary forms, with or without
  37.  *  modification, are permitted provided that the following conditions are
  38.  *  met:
  39.  * 
  40.  * Redistributions of source code must retain the above copyright
  41.  *  notice, this list of conditions and the following disclaimer.
  42.  * Redistributions in binary form must reproduce the above copyright
  43.  *  notice, this list of conditions and the following disclaimer in the
  44.  *  documentation and/or other materials provided with the distribution.
  45.  *      Neither the name of the Intel Corporation nor the names of its
  46.  *  contributors may be used to endorse or promote products derived from
  47.  *  this software without specific prior written permission.
  48.  *  
  49.  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  50.  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  51.  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  52.  *  PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE INTEL OR ITS
  53.  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  54.  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  55.  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  56.  *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  57.  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  58.  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  59.  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  60.  * 
  61.  * 
  62.  */
  63. /*  
  64.  *  Authors: Philip Buonadonna, Jaein Jeong, Joe Polastre
  65.  *  Date last modified: $Revision: 1.6 $
  66.  *
  67.  * This module provides the layer2 functionality for the mica2 radio.
  68.  * While the internal architecture of this module is not CC1000 specific,
  69.  * It does make some CC1000 specific calls via CC1000Control.
  70.  * 
  71.  */
  72. /**
  73.  * @author Philip Buonadonna
  74.  * @author Jaein Jeong
  75.  * @author Joe Polastre
  76.  */
  77.   
  78. includes crc;
  79. includes CC1000Const;
  80. module CC1000RadioIntM {
  81.   provides {
  82.     interface StdControl;
  83.     interface BareSendMsg as Send;
  84.     interface ReceiveMsg as Receive;
  85.     interface RadioCoordinator as RadioSendCoordinator;
  86.     interface RadioCoordinator as RadioReceiveCoordinator;
  87.     interface MacControl;
  88.     interface MacBackoff;
  89.     interface LowPowerListening;
  90.     // legacy commands supported, but should now use the
  91.     // Low Power Listening interface
  92.     async command result_t SetListeningMode(uint8_t power);
  93.     async command uint8_t GetListeningMode();
  94.     async command result_t SetTransmitMode(uint8_t power);
  95.     async command uint8_t GetTransmitMode();
  96.     // Used for debugging the noise floor (gets the current squelch value)
  97.     async command uint16_t GetSquelch();
  98.     // Used for debugging; gets an estimate of the power consumed by the radio
  99.     async command uint16_t GetPower();
  100.     async command uint16_t GetPower_tx();
  101.     async command uint16_t GetPower_rx();
  102.     async command uint16_t GetPower_sp();
  103.     async command uint16_t GetDataSent();
  104.     async command result_t ResetDataSent();
  105.     async command result_t ResetPower();
  106.   }
  107.   uses {
  108.     interface PowerManagement;
  109.     interface StdControl as CC1000StdControl;
  110.     interface CC1000Control;
  111.     interface Random;
  112.     interface ADCControl;
  113.     interface ADC as RSSIADC;
  114.     interface SpiByteFifo;
  115.     interface StdControl as TimerControl;
  116.     interface Timer as WakeupTimer;
  117.     interface Timer as SquelchTimer;
  118.     interface Leds;
  119.   }
  120. }
  121. implementation {
  122. #ifdef ZMAC_DEBUG
  123. #include "SODebug.h"
  124. #endif
  125.   enum {
  126.     NULL_STATE,
  127.     TX_STATE,
  128.     DISABLED_STATE,
  129.     IDLE_STATE,
  130.     PRETX_STATE,
  131.     SYNC_STATE,
  132.     RX_STATE,
  133.     SENDING_ACK,
  134.     POWER_DOWN_STATE,
  135.     PULSE_CHECK_STATE,
  136.   };
  137.   enum {
  138.     TXSTATE_WAIT,
  139.     TXSTATE_START,
  140.     TXSTATE_PREAMBLE,
  141.     TXSTATE_SYNC,
  142.     TXSTATE_DATA,
  143.     TXSTATE_CRC,
  144.     TXSTATE_FLUSH,
  145.     TXSTATE_WAIT_FOR_ACK,
  146.     TXSTATE_READ_ACK,
  147.     TXSTATE_DONE
  148.   };
  149.   enum {
  150.     SYNC_BYTE = 0x33,
  151.     NSYNC_BYTE = 0xcc,
  152.     SYNC_WORD = 0x33cc,
  153.     NSYNC_WORD = 0xcc33,
  154.     ACK_LENGTH = 16,
  155.     MAX_ACK_WAIT = 18,
  156.     TIME_BETWEEN_CHECKS = 50,
  157.     TIME_AFTER_CHECK = 30,
  158.     CHECK_MA_COUNT = 100, //8888,
  159.     SEND_MA_COUNT = 100, //7200,
  160.     PREAMBLE_LENGTH_TO_BASE = 8,
  161.     RECEIVE_MA_COUNT = 100, //9600
  162.   };
  163.   uint8_t ack_code[5] = {0xab, 0xba, 0x83, 0xaa, 0xaa};
  164.   uint8_t RadioState;
  165.   uint8_t RadioTxState;
  166.   norace uint8_t iRSSIcount;
  167.   uint8_t RSSIInitState;
  168.   uint8_t iSquelchCount;
  169.   uint16_t txlength;
  170.   uint16_t rxlength;
  171.   TOS_MsgPtr txbufptr;  // pointer to transmit buffer
  172.   TOS_MsgPtr rxbufptr;  // pointer to receive buffer
  173.   TOS_Msg RxBuf; // save received messages
  174.   uint8_t NextTxByte;
  175.   uint8_t lplpower;        //  low power listening mode
  176.   uint8_t lplpowertx;      //  low power listening transmit mode
  177.   uint16_t preamblelen;    //  current length of the preamble
  178.   uint16_t sleeptime;       //  current check interval (sleep time)
  179.  
  180.   uint16_t PreambleCount;   //  found a valid preamble
  181.   uint8_t SOFCount;
  182.   uint16_t search_word;
  183.   union {
  184.     uint16_t W;
  185.     struct {
  186.       uint8_t LSB;
  187.       uint8_t MSB;
  188.     };
  189.   } RxShiftBuf;
  190.   uint8_t RxBitOffset; // bit offset for spibus
  191.   uint16_t RxByteCnt; // received byte counter
  192.   uint16_t TxByteCnt;
  193.   uint16_t RSSISampleFreq; // in Bytes rcvd per sample
  194.   norace bool bInvertRxData; // data inverted
  195.   norace bool bTxPending;
  196.   bool bAckEnable;
  197.   bool bCCAEnable;
  198.   bool bTxBusy;
  199.   bool bRSSIValid;
  200.   uint16_t CC1K_PulseLevel;
  201.   uint16_t usRunningCRC; // Running CRC variable
  202.   uint16_t usRSSIVal;
  203.   uint16_t usSquelchVal;
  204.   uint16_t usTempSquelch;
  205.   uint8_t usSquelchIndex;
  206.   norace uint8_t pulse_check_count;
  207.   norace uint16_t pulse_check_sum;
  208.   norace uint16_t send_sum;
  209.   norace uint16_t receive_sum;
  210.   norace uint16_t power_sum;
  211.   norace uint16_t sp_sum;
  212.   norace uint16_t rx_sum;
  213.   norace uint16_t tx_sum;
  214.   norace uint16_t dataSent;
  215.   uint16_t usSquelchTable[CC1K_SquelchTableSize];
  216.   int16_t sMacDelay;    // MAC delay for the next transmission
  217.   // XXX-PB:
  218.   // Here's the deal, the mica (RFM) radio stacks used TOS_LOCAL_ADDRESS
  219.   // to determine if an L2 ack was reqd.  This stack doesn't do L2 acks
  220.   // and, thus doesn't need it.  HOWEVER, some set-mote-id versions
  221.   // break if this symbol is missing from the binary.
  222.   // Thus, I put this LocalAddr here and set it to TOS_LOCAL_ADDRESS
  223.   // to keep things happy for now.
  224.   volatile uint16_t LocalAddr;
  225.   ///**********************************************************
  226.   //* local function definitions
  227.   //**********************************************************/
  228.   /*
  229.     int sortByShort(const void *x, const void *y) {
  230.     uint16_t* x1 = (uint16_t*)x;
  231.     uint16_t* y1 = (uint16_t*)y;
  232.     if (x1[0] > y1[0]) return -1;
  233.     if (x1[0] == y1[0]) return 0;
  234.     if (x1[0] < y1[0]) return 1;
  235.     return 0; // shouldn't reach here becasue it covers all the cases
  236.     }
  237.   */
  238.   task void adjustSquelch() {
  239.     uint16_t tempArray[CC1K_SquelchTableSize];
  240.     char i,j,min; 
  241.     uint16_t min_value;
  242.     uint32_t tempsquelch;
  243.     atomic {
  244.       usSquelchTable[usSquelchIndex] = usTempSquelch;
  245.       usSquelchIndex++;
  246.       if (usSquelchIndex >= CC1K_SquelchTableSize)
  247.         usSquelchIndex = 0;
  248.       if (iSquelchCount <= CC1K_SquelchCount)
  249.         iSquelchCount++;  
  250.     }
  251.     for (i=0; i<CC1K_SquelchTableSize; i++) {
  252.       tempArray[(int)i] = usSquelchTable[(int)i];
  253.     }
  254.     min = 0;
  255.     //    for (j = 0; j < ((CC1K_SquelchTableSize) >> 1); j++) {
  256.     for (j = 0; j < 3; j++) {
  257.       for (i = 1; i < CC1K_SquelchTableSize; i++) {
  258.         if ((tempArray[(int)i] != 0xFFFF) && 
  259.             ((tempArray[(int)i] > tempArray[(int)min]) ||
  260.              (tempArray[(int)min] == 0xFFFF))) {
  261.           min = i;
  262.         }
  263.       }
  264.       min_value = tempArray[(int)min];
  265.       tempArray[(int)min] = 0xFFFF;
  266.     }
  267.     tempsquelch = ((uint32_t)(usSquelchVal << 5) + (uint32_t)(min_value << 1));
  268.     atomic usSquelchVal = (uint16_t)((tempsquelch / 34) & 0x0FFFF);
  269.     /*
  270.     // XXX: qsort actually causes ~600bits/sec lower bandwidth... why???
  271.     //
  272.     qsort (tempArray,CC1K_SquelchTableSize, sizeof(uint16_t),sortByShort);
  273.     min_value = tempArray[CC1K_SquelchTableSize >> 1];
  274.     atomic usSquelchVal = ((usSquelchVal << 5) + (min_value << 1)) / 34;
  275.     */
  276.   }
  277.   task void PacketRcvd() {
  278.     TOS_MsgPtr pBuf;
  279.     atomic {
  280.       rxbufptr->time = 0;
  281.       pBuf = rxbufptr;
  282.     }
  283. #ifdef ZMAC_DEBUG
  284.     SODbg(DBG_USR2, "Received packet of type %u and crc %un", pBuf->type, pBuf->crc);
  285. #endif
  286.     pBuf = signal Receive.receive((TOS_MsgPtr)pBuf);
  287.     atomic {
  288.       if (pBuf) 
  289.         rxbufptr = pBuf;
  290.       rxbufptr->length = 0;
  291.     }
  292.     call SpiByteFifo.enableIntr();
  293.   }
  294.   
  295.   task void PacketSent() {
  296.     TOS_MsgPtr pBuf; //store buf on stack 
  297.     atomic {
  298.       txbufptr->time = 0;
  299.       pBuf = txbufptr;
  300.     }
  301.     if(txbufptr->type == AM_MULTIHOP)
  302.       dataSent++;
  303.     signal Send.sendDone((TOS_MsgPtr)pBuf,SUCCESS);
  304.     atomic bTxBusy = FALSE;
  305.   }
  306.   ///**********************************************************
  307.   //* Exported interface functions
  308.   //**********************************************************/
  309.   
  310.   command result_t StdControl.init() {
  311.     char i;
  312.     atomic {
  313.       RadioState = DISABLED_STATE;
  314.       RadioTxState = TXSTATE_PREAMBLE;
  315.       rxbufptr = &RxBuf;
  316.       rxbufptr->length = 0;
  317.       rxlength = MSG_DATA_SIZE-2;
  318.       RxBitOffset = 0;
  319.       iSquelchCount = 0;
  320.       
  321.       PreambleCount = 0;
  322.       RSSISampleFreq = 0;
  323.       RxShiftBuf.W = 0;
  324.       iRSSIcount = 0;
  325.       bTxPending = FALSE;
  326.       bTxBusy = FALSE;
  327.       bRSSIValid = FALSE;
  328.       bAckEnable = FALSE;
  329.       bCCAEnable = TRUE;
  330.       CC1K_PulseLevel = 300;
  331.       sMacDelay = -1;
  332.       usRSSIVal = -1;
  333.       usSquelchIndex = 0;
  334.       pulse_check_count = 0;
  335.       lplpower =  0;//0x87;
  336.       RSSIInitState = NULL_STATE;
  337.       //      if(TOS_LOCAL_ADDRESS == 0) lplpower = 0;
  338.       //      lplpowertx = 7;
  339.       usSquelchVal = CC1K_SquelchInit;
  340.     }
  341.     for (i = 0; i < CC1K_SquelchTableSize; i++)
  342.       usSquelchTable[(int)i] = CC1K_SquelchInit;
  343.     call SpiByteFifo.initSlave(); // set spi bus to slave mode
  344.     call CC1000StdControl.init();
  345.     call CC1000Control.SelectLock(0x9); // Select MANCHESTER VIOLATION
  346.     bInvertRxData = call CC1000Control.GetLOStatus();
  347.     call ADCControl.bindPort(TOS_ADC_CC_RSSI_PORT,TOSH_ACTUAL_CC_RSSI_PORT);
  348.     call ADCControl.init();
  349.     call Random.init();
  350.     call TimerControl.init();
  351.     LocalAddr = TOS_LOCAL_ADDRESS;
  352. #ifdef ZMAC_DEBUG
  353.     init_debug();
  354. #endif
  355.     return SUCCESS;
  356.   }
  357.   
  358.   /**
  359.    * Get the current Low Power Listening transmit mode
  360.    * @return mode number (see SetListeningMode)
  361.    */
  362.   async command uint8_t LowPowerListening.GetTransmitMode() {
  363.     return lplpowertx;
  364.   }
  365.   // legacy support
  366.   async command uint8_t GetTransmitMode() {
  367.     return call LowPowerListening.GetTransmitMode();
  368.   }
  369.   /**
  370.    * Set the transmit mode.  This allows for hybrid schemes where
  371.    * the transmit mode is different than the receive mode.
  372.    * Use SetListeningMode first, then change the mode with SetTransmitMode.
  373.    *
  374.    * @param mode mode number (see SetListeningMode)
  375.    * @return SUCCESS if the mode was successfully changed
  376.    */
  377.   async command result_t LowPowerListening.SetTransmitMode(uint8_t power) {
  378.     if ((power >= CC1K_LPL_STATES) || (power == lplpowertx))
  379.       return FAIL;
  380.     // check if the radio is currently doing something
  381.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  382.                           (RadioState == IDLE_STATE) ||
  383.                           (RadioState == DISABLED_STATE))) {
  384.       atomic {
  385.         lplpowertx = power;
  386.         preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8)
  387.                        | PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  388.       }
  389.       return SUCCESS;
  390.     }
  391.     return FAIL;
  392.   }
  393.   // legacy support
  394.   async command result_t SetTransmitMode(uint8_t power) {
  395.     return call LowPowerListening.SetTransmitMode(power);
  396.   }
  397.   /**
  398.    * Set the current Low Power Listening mode.
  399.    * Setting the LPL mode sets both the check interval and preamble length.
  400.    *
  401.    * Modes include:
  402.    *  0 = Radio full on
  403.    *  1 = 10ms check interval
  404.    *  2 = 25ms check interval
  405.    *  3 = 50ms check interval
  406.    *  4 = 100ms check interval (recommended)
  407.    *  5 = 200ms check interval
  408.    *  6 = 400ms check interval
  409.    *  7 = 800ms check interval
  410.    *  8 = 1600ms check interval
  411.    *
  412.    * @param mode the mode number
  413.    * @return SUCCESS if the mode was successfully changed
  414.    */
  415.   async command result_t LowPowerListening.SetListeningMode(uint8_t power) {
  416.     // valid low power listening values are 0 to 8
  417.     // 0 is "always on" and 8 is lowest duty cycle
  418.     if ((power >= CC1K_LPL_STATES) || (power == lplpower))
  419.       return FAIL;
  420.     // check if the radio is currently doing something
  421.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  422.                           (RadioState == IDLE_STATE) ||
  423.                           (RadioState == DISABLED_STATE))) {
  424.       // change receiving function in CC1000Radio
  425.       call WakeupTimer.stop();
  426.       atomic {
  427.         if (lplpower == lplpowertx) {
  428.           lplpowertx = power;
  429.         }
  430.         lplpower = power;
  431.       }
  432.       // if successful, change power here
  433.       if (RadioState == IDLE_STATE) {
  434.         RadioState = DISABLED_STATE;
  435.         call StdControl.stop();
  436.         call StdControl.start();
  437.       }
  438.       if (RadioState == POWER_DOWN_STATE) {
  439.         RadioState = DISABLED_STATE;
  440.         call StdControl.start();
  441.         call PowerManagement.adjustPower();
  442.       }
  443.     }
  444.     else {
  445.       return FAIL;
  446.     }
  447.     return SUCCESS;
  448.   }
  449.   // legacy support
  450.   async command result_t SetListeningMode(uint8_t power) {
  451.     return call SetListeningMode(power);
  452.   }
  453.   /**
  454.    * Gets the state of low power listening on the chipcon radio.
  455.    * @return Current low power listening state value
  456.    */
  457.   async command uint8_t LowPowerListening.GetListeningMode() {
  458.     return lplpower;
  459.   }
  460.   // legacy support
  461.   async command uint8_t GetListeningMode() {
  462.     return call LowPowerListening.GetListeningMode();
  463.   } 
  464.   /**
  465.    * Set the preamble length of outgoing packets
  466.    *
  467.    * @param bytes length of the preamble in bytes
  468.    * @return SUCCESS if the preamble length was successfully changed
  469.    */
  470.   async command result_t LowPowerListening.SetPreambleLength(uint16_t bytes) {
  471.     result_t result = FAIL;
  472.     atomic {
  473.       if (RadioState != TX_STATE) {
  474.         preamblelen = bytes;
  475.         result = SUCCESS;
  476.       }
  477.     }
  478.     return result;
  479.   }
  480.   /**
  481.    * Get the preamble length of outgoing packets
  482.    *
  483.    * @return length of the preamble in bytes
  484.    */
  485.   async command uint16_t LowPowerListening.GetPreambleLength() {
  486.     return preamblelen;
  487.   }
  488.   /**
  489.    * Set the check interval (time between waking up and sampling
  490.    * the radio for activity in low power listening)
  491.    *
  492.    * @param ms check interval in milliseconds
  493.    * @return SUCCESS if the check interval was successfully changed
  494.    */
  495.   async command result_t LowPowerListening.SetCheckInterval(uint16_t ms) {
  496.     // sleep time will go into effect after the next wakeup time
  497.     atomic sleeptime = ms;
  498.     return SUCCESS;
  499.   }
  500.   /**
  501.    * Get the check interval currently used by low power listening
  502.    *
  503.    * @return length of the check interval in milliseconds
  504.    */
  505.   async command uint16_t LowPowerListening.GetCheckInterval() {
  506.     return sleeptime;
  507.   }
  508.   event result_t SquelchTimer.fired() {
  509.     char currentRadioState;
  510.     atomic currentRadioState = RadioState;
  511.     if (currentRadioState == IDLE_STATE) {
  512.       atomic RSSIInitState = currentRadioState;
  513.       call RSSIADC.getData();
  514.     }
  515.     return SUCCESS;
  516.   }
  517.   event result_t WakeupTimer.fired() {
  518.     uint8_t currentRadioState;
  519.     if (lplpower == 0)
  520.       return SUCCESS;
  521.     atomic currentRadioState = RadioState;
  522.     switch(currentRadioState) {
  523.     case IDLE_STATE:
  524.       if (!bTxPending) {
  525.         atomic {
  526.           RadioState = POWER_DOWN_STATE;
  527.           call SpiByteFifo.disableIntr();
  528.         }
  529.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  530.         call SquelchTimer.stop();
  531.         call CC1000StdControl.stop();
  532.       } else {
  533.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  534.       }
  535.       break;
  536.     case POWER_DOWN_STATE:
  537.       atomic RadioState = PULSE_CHECK_STATE;
  538.       pulse_check_count = 0;
  539.       call CC1000StdControl.start();
  540.       call CC1000Control.BIASOn();
  541.       call WakeupTimer.start(TIMER_ONE_SHOT, 1);
  542.       return SUCCESS;
  543.       break;
  544.     case PULSE_CHECK_STATE:
  545.       call CC1000Control.RxMode();
  546.       if(!(call RSSIADC.getData())){
  547.         call WakeupTimer.start(TIMER_ONE_SHOT, TIME_BETWEEN_CHECKS);
  548.         atomic RadioState = POWER_DOWN_STATE;
  549.       }
  550.       else {
  551.         TOSH_uwait(80);
  552.       }
  553.       call CC1000StdControl.stop();
  554.       pulse_check_sum ++;
  555.       break;
  556.     default:
  557.       call WakeupTimer.start(TIMER_ONE_SHOT, 5);
  558.     }
  559.     return SUCCESS;
  560.   }
  561.   command result_t StdControl.stop() {
  562.     atomic RadioState = DISABLED_STATE;
  563.     call SquelchTimer.stop();
  564.     call WakeupTimer.stop();
  565.     call CC1000StdControl.stop();
  566.     call SpiByteFifo.disableIntr(); // disable spi interrupt
  567.     return SUCCESS;
  568.   }
  569.   command result_t StdControl.start() {
  570.     uint8_t currentRadioState;
  571.     atomic currentRadioState = RadioState;
  572.     if (currentRadioState == DISABLED_STATE) {
  573.       atomic {
  574.         rxbufptr->length = 0;
  575.         RadioState  = IDLE_STATE;
  576.         bTxPending = bTxBusy = FALSE;
  577.         sMacDelay = -1;
  578.         if(SLEEPTIME > 0){
  579.           sleeptime = SLEEPTIME;
  580.           preamblelen = PREAMBLELEN;
  581.         } else{
  582.           lplpower = lplpowertx = 0;
  583.           sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) |
  584.                        PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1]));
  585.           preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) |
  586.                          PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  587.         }
  588.       }
  589.       // all power on, captain!
  590.       rxbufptr->length = 0;
  591.       atomic RadioState = IDLE_STATE;
  592.       call CC1000StdControl.start();
  593.       call CC1000Control.BIASOn();
  594.       call SpiByteFifo.rxMode(); // SPI to miso
  595.       call CC1000Control.RxMode();
  596.       if (iSquelchCount > CC1K_SquelchCount)
  597.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  598.       else
  599.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  600.       call SpiByteFifo.enableIntr(); // enable spi interrupt
  601.       if (lplpower > 0) {
  602.         // set a time to start sleeping after measuring the noise floor
  603.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_SquelchIntervalSlow);
  604.       }
  605.     }
  606.     return SUCCESS;
  607.   }
  608.   command result_t Send.send(TOS_MsgPtr pMsg) {
  609.     result_t Result = SUCCESS;
  610.     uint8_t currentRadioState = 0;
  611.     atomic {
  612.       if (bTxBusy) {
  613.         Result = FAIL;
  614.       }
  615.       else {
  616.         bTxBusy = TRUE;
  617.         txbufptr = pMsg;
  618.         txlength = pMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2); 
  619.         // initially back off [1,32] bytes (approx 2/3 packet)
  620.         if (bCCAEnable)
  621.           sMacDelay = signal MacBackoff.initialBackoff(pMsg);
  622.         else
  623.           sMacDelay = 0;
  624.         bTxPending = TRUE;
  625.       }
  626.       currentRadioState = RadioState;
  627.     }
  628.     if (Result) {
  629.       // if we're off, start the radio
  630.       if (currentRadioState == POWER_DOWN_STATE) {
  631.         // disable wakeup timer
  632.         atomic RadioState = IDLE_STATE;
  633.         call WakeupTimer.stop();
  634.         call CC1000StdControl.start();
  635.         call CC1000Control.BIASOn();
  636.         call CC1000Control.RxMode();
  637.         call SpiByteFifo.rxMode(); // SPI to miso
  638.         call SpiByteFifo.enableIntr(); // enable spi interrupt
  639.         if (iSquelchCount > CC1K_SquelchCount)
  640.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  641.         else
  642.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  643.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
  644.       }
  645.     }
  646.     return Result;
  647.   }
  648.   
  649.   /**********************************************************
  650.    * make a spibus interrupt handler
  651.    * needs to handle interrupts for transmit delay
  652.    * and then go into byte transmit mode with
  653.    *   timer1 baudrate delay as interrupt handler
  654.    * else
  655.    * needs to handle interrupts for byte read and detect preamble
  656.    *  then handle reading a packet
  657.    * PB - We can use this interrupt handler as a transmit scheduler
  658.    * because the CC1000 continuously clocks in data, regarless
  659.    * of whether it's good or not.  Thus, this routine will be called
  660.    * on every 8 ticks of DCLK. 
  661.    **********************************************************/
  662.   async event result_t SpiByteFifo.dataReady(uint8_t data_in) {
  663.     
  664.     signal RadioSendCoordinator.blockTimer();
  665.     signal RadioReceiveCoordinator.blockTimer();
  666.     if (bInvertRxData) 
  667.       data_in = ~data_in;
  668. #ifdef ENABLE_UART_DEBUG
  669.     UARTPutChar(RadioState);
  670. #endif
  671.     switch (RadioState) {
  672.     case TX_STATE:
  673.       {
  674.         call SpiByteFifo.writeByte(NextTxByte);
  675.         TxByteCnt++;
  676.         switch (RadioTxState) {
  677.         case TXSTATE_PREAMBLE:
  678.           send_sum ++;
  679.           if (!(TxByteCnt < preamblelen)||
  680.               (txbufptr->strength == 0xffff && TxByteCnt >= PREAMBLE_LENGTH_TO_BASE)) {
  681.             NextTxByte = SYNC_BYTE;
  682.             RadioTxState = TXSTATE_SYNC;
  683.           }
  684.           break;
  685.         case TXSTATE_SYNC:
  686.           send_sum ++;
  687.           NextTxByte = NSYNC_BYTE;
  688.           RadioTxState = TXSTATE_DATA;
  689.           TxByteCnt = -1;
  690.           // for Time Sync services
  691.           signal RadioSendCoordinator.startSymbol(8, 0, txbufptr); 
  692.           break;
  693.         case TXSTATE_DATA:
  694.           send_sum ++;
  695.           if ((uint8_t)(TxByteCnt) < txlength) {
  696.             NextTxByte = ((uint8_t *)txbufptr)[(TxByteCnt)];
  697.             usRunningCRC = crcByte(usRunningCRC,NextTxByte);
  698.             signal RadioSendCoordinator.byte(txbufptr, (uint8_t)TxByteCnt); // Time Sync
  699.           }
  700.           else {
  701.             NextTxByte = (uint8_t)(usRunningCRC);
  702.             RadioTxState = TXSTATE_CRC;
  703.           }
  704.           break;
  705.         case TXSTATE_CRC:
  706.           send_sum ++;
  707.           NextTxByte = (uint8_t)(usRunningCRC>>8);
  708.           RadioTxState = TXSTATE_FLUSH;
  709.           TxByteCnt = 0;
  710.           break;
  711.         case TXSTATE_FLUSH:
  712.           send_sum ++;
  713.           if (TxByteCnt > 3) {
  714.             TxByteCnt = 0;
  715.             if (bAckEnable) {
  716.               RadioTxState = TXSTATE_WAIT_FOR_ACK;
  717.             }
  718.             else {
  719.               call SpiByteFifo.rxMode();
  720.               call CC1000Control.RxMode();
  721.               RadioTxState = TXSTATE_DONE;
  722.             }
  723.           }
  724.           break;
  725.         case TXSTATE_WAIT_FOR_ACK:
  726.           if(TxByteCnt == 1){
  727.             send_sum ++;
  728.             call SpiByteFifo.rxMode();
  729.             call CC1000Control.RxMode();
  730.             break;
  731.           }
  732.           receive_sum ++;
  733.           if (TxByteCnt > 3) {
  734.             RadioTxState = TXSTATE_READ_ACK;
  735.             TxByteCnt = 0;
  736.             search_word = 0;
  737.           }
  738.           break;
  739.         case TXSTATE_READ_ACK:
  740.           {
  741.             uint8_t i;
  742.             receive_sum ++;
  743.             for(i = 0; i < 8; i ++){
  744.               search_word <<= 1;
  745.               if(data_in & 0x80) search_word |=  0x1;
  746.               data_in <<= 1;
  747.               if (search_word == 0xba83){
  748.                 txbufptr->ack = 1;
  749.                 RadioTxState = TXSTATE_DONE;
  750.                 return SUCCESS;
  751.               }
  752.             }
  753.           }
  754.           if(TxByteCnt >= MAX_ACK_WAIT){
  755.             txbufptr->ack = 0;
  756.             RadioTxState = TXSTATE_DONE;
  757.           }
  758.           break;
  759.         case TXSTATE_DONE:
  760.         default:
  761.           bTxPending = FALSE;
  762.           if (post PacketSent()) {
  763.             // If the post operation succeeds, goto Idle
  764.             // otherwise, we'll try again.
  765.             RadioState = IDLE_STATE;
  766.             RSSIInitState = RadioState;
  767.             call RSSIADC.getData();
  768.           }
  769.           break;
  770.         }
  771.       }
  772.       break;
  773.     case DISABLED_STATE:
  774.       break;
  775.     case IDLE_STATE: 
  776.       {
  777.         receive_sum ++;
  778.         if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  779.           PreambleCount++;
  780.           if (PreambleCount > CC1K_ValidPrecursor) {
  781.             PreambleCount = SOFCount = 0;
  782.             RxBitOffset = RxByteCnt = 0;
  783.             usRunningCRC = 0;
  784.             rxlength = MSG_DATA_SIZE-2;
  785.             RadioState = SYNC_STATE;
  786.           }
  787.         }
  788.         else if (bTxPending && (--sMacDelay <= 0)) {
  789.           RadioState = PRETX_STATE;
  790.           RSSIInitState = PRETX_STATE;
  791.           bRSSIValid = FALSE;
  792.           iRSSIcount = 0;
  793.           PreambleCount = 0;
  794.           call RSSIADC.getData();
  795.         }
  796.       }
  797.       break;
  798.     case PRETX_STATE:
  799.       {
  800.         receive_sum ++;
  801.         if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  802.           // Back to the penalty box.
  803.           sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
  804.           RadioState = IDLE_STATE;
  805.         }
  806.       }
  807.       break;
  808.     case SYNC_STATE:
  809.       {
  810.         // draw in the preamble bytes and look for a sync byte
  811.         // save the data in a short with last byte received as msbyte
  812.         //    and current byte received as the lsbyte.
  813.         // use a bit shift compare to find the byte boundary for the sync byte
  814.         // retain the shift value and use it to collect all of the packet data
  815.         // check for data inversion, and restore proper polarity 
  816.         // XXX-PB: Don't do this.
  817.         uint8_t i;
  818.         receive_sum ++;
  819.         if ((data_in == 0xaa) || (data_in == 0x55)) {
  820.           // It is actually possible to have the LAST BIT of the incoming
  821.           // data be part of the Sync Byte.  SO, we need to store that
  822.           // However, the next byte should definitely not have this pattern.
  823.           // XXX-PB: Do we need to check for excessive preamble?
  824.           RxShiftBuf.MSB = data_in;
  825.         }
  826.         else {
  827.           // TODO: Modify to be tolerant of bad bits in the preamble...
  828.           uint16_t usTmp;
  829.           switch (SOFCount) {
  830.           case 0:
  831.             RxShiftBuf.LSB = data_in;
  832.             break;
  833.   
  834.           case 1:
  835.           case 2: 
  836.           case 3: 
  837.           case 4: 
  838.           case 5: 
  839.             // bit shift the data in with previous sample to find sync
  840.             usTmp = RxShiftBuf.W;
  841.             RxShiftBuf.W <<= 8;
  842.             RxShiftBuf.LSB = data_in;
  843.             for(i=0;i<8;i++) {
  844.               usTmp <<= 1;
  845.               if(data_in & 0x80)
  846.                 usTmp  |=  0x1;
  847.               data_in <<= 1;
  848.               // check for sync bytes
  849.               if (usTmp == SYNC_WORD) {
  850.                 if (rxbufptr->length !=0) {
  851.                   call Leds.redToggle();
  852.                   RadioState = IDLE_STATE;
  853.                 }
  854.                 else {
  855.                   RadioState = RX_STATE;
  856.                   RSSIInitState = RX_STATE;
  857.                   call RSSIADC.getData();
  858.                   RxBitOffset = 7-i;
  859.                   // For time sync services
  860.                   signal RadioReceiveCoordinator.startSymbol(8, RxBitOffset, rxbufptr); 
  861.                 }
  862.                 break;
  863.               }
  864.             }
  865.             break;
  866.           default:
  867.             // We didn't find it after a reasonable number of tries, so....
  868.             RadioState = IDLE_STATE;  // Ensures we wait till the end of the transmission
  869.             break;
  870.           }
  871.           SOFCount++;
  872.         }
  873.       }
  874.       break;
  875.       //  collect the data and shift into double buffer
  876.       //  shift out data by correct offset
  877.       //  invert the data if necessary
  878.       //  stop after the correct packet length is read
  879.       //  return notification to upper levels
  880.       //  go back to idle state
  881.     case RX_STATE:
  882.       {
  883.         char Byte;
  884.         receive_sum ++;
  885.         RxShiftBuf.W <<=8;
  886.         RxShiftBuf.LSB = data_in;
  887.         Byte = (RxShiftBuf.W >> RxBitOffset);
  888.         ((char*)rxbufptr)[(int)RxByteCnt] = Byte;
  889.         RxByteCnt++;
  890.         signal RadioReceiveCoordinator.byte(rxbufptr, (uint8_t)RxByteCnt);
  891.         if (RxByteCnt < rxlength) {
  892.           usRunningCRC = crcByte(usRunningCRC,Byte);
  893.           if (RxByteCnt == (offsetof(struct TOS_Msg,length) + 
  894.                             sizeof(((struct TOS_Msg *)0)->length))) {
  895.             rxlength = rxbufptr->length;
  896.             if (rxlength > TOSH_DATA_LENGTH) {
  897.               // The packet's screwed up, so just dump it
  898.               rxbufptr->length = 0;
  899.               RadioState = IDLE_STATE;  // Waits till end of transmission
  900.               return SUCCESS;
  901.             }
  902.             //Add in the header size
  903.             rxlength += offsetof(struct TOS_Msg,data);
  904.           }
  905.         }
  906.         else if (RxByteCnt == rxlength) {
  907.           usRunningCRC = crcByte(usRunningCRC,Byte);
  908.           // Shift index ahead to the crc field.
  909.           RxByteCnt = offsetof(struct TOS_Msg,crc);
  910.         }
  911.         else if (RxByteCnt >= MSG_DATA_SIZE) { 
  912.           // Packet filtering based on bad CRC's is done at higher layers.
  913.           // So sayeth the TOS weenies.
  914.           if (rxbufptr->crc == usRunningCRC) {
  915.             rxbufptr->crc = 1;
  916.             if(bAckEnable && (rxbufptr->addr == TOS_LOCAL_ADDRESS)){
  917.               RadioState = SENDING_ACK; 
  918.               call CC1000Control.TxMode();
  919.               call SpiByteFifo.txMode();
  920.               call SpiByteFifo.writeByte(0xaa);
  921.               RxByteCnt = 0;
  922.               return SUCCESS; 
  923.             }
  924.           } else {
  925.             rxbufptr->crc = 0;
  926.           }
  927.           call SpiByteFifo.disableIntr();
  928.   
  929.           RadioState = IDLE_STATE; //DISABLED_STATE;
  930.           rxbufptr->strength = usRSSIVal;
  931.           if (!(post PacketRcvd())) {
  932.             // If there are insufficient resources to process the incoming packet
  933.             // we drop it
  934.             rxbufptr->length = 0;
  935.             RadioState = IDLE_STATE;
  936.             call SpiByteFifo.enableIntr();
  937.           }
  938.           RSSIInitState = RadioState;
  939.           call RSSIADC.getData();
  940.         }
  941.       }
  942.       break;
  943.     case SENDING_ACK:
  944.       {
  945.         send_sum ++;
  946.         RxByteCnt++;
  947.         if (RxByteCnt >= ACK_LENGTH) { 
  948.           call CC1000Control.RxMode();
  949.           call SpiByteFifo.rxMode();
  950.           call SpiByteFifo.disableIntr();
  951.           RadioState = IDLE_STATE; //DISABLED_STATE;
  952.           rxbufptr->strength = usRSSIVal;
  953.           if (!(post PacketRcvd())) {
  954.             rxbufptr->length = 0;
  955.             RadioState = IDLE_STATE;
  956.             call SpiByteFifo.enableIntr();
  957.           }
  958.         }else if(RxByteCnt >= ACK_LENGTH - sizeof(ack_code)){
  959.           call SpiByteFifo.writeByte(ack_code[RxByteCnt + sizeof(ack_code) - ACK_LENGTH]);
  960.         }
  961.       }
  962.       break;
  963.     default:
  964.       break;
  965.     }
  966.     if(pulse_check_sum > CHECK_MA_COUNT){
  967.       power_sum ++;
  968.       sp_sum++;
  969.       pulse_check_sum -= CHECK_MA_COUNT;
  970.     }
  971.     if(send_sum > SEND_MA_COUNT){
  972.       power_sum ++;
  973.       tx_sum++;
  974.       send_sum -= SEND_MA_COUNT;
  975.     }
  976.     if(receive_sum > RECEIVE_MA_COUNT){
  977.       power_sum ++;
  978.       rx_sum++;
  979.       receive_sum -= RECEIVE_MA_COUNT;
  980.     }
  981.     return SUCCESS;
  982.   }
  983.   task void IdleTimerTask(){
  984.     if (iSquelchCount > CC1K_SquelchCount)
  985.       call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  986.     else
  987.       call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  988.     call WakeupTimer.start(TIMER_ONE_SHOT, TIME_AFTER_CHECK);
  989.     /*if(pulse_check_sum > CHECK_MA_COUNT){
  990.       power_sum ++;
  991.       pulse_check_sum -= CHECK_MA_COUNT;
  992.       }
  993.       if(send_sum > SEND_MA_COUNT){
  994.       power_sum ++;
  995.       send_sum -= SEND_MA_COUNT;
  996.       }
  997.       if(receive_sum > RECEIVE_MA_COUNT){
  998.       power_sum ++;
  999.       receive_sum -= RECEIVE_MA_COUNT;
  1000.       }*/
  1001.   }
  1002.   task void SleepTimerTask(){
  1003.     call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  1004.   }
  1005.   async event result_t RSSIADC.dataReady(uint16_t data) { 
  1006.     atomic
  1007.       {
  1008.         uint8_t currentRadioState;
  1009.         // TOSH_CLR_PW3_PIN();
  1010.         currentRadioState = RadioState;
  1011.         // find the maximum RSSI value over CC1K_MAX_RSSI_SAMPLES
  1012.         switch(currentRadioState) {
  1013.         case IDLE_STATE:
  1014.           if (RSSIInitState == IDLE_STATE) {
  1015.             atomic usTempSquelch = data;
  1016.             post adjustSquelch();
  1017.           }
  1018.           RSSIInitState = NULL_STATE;
  1019.           break;
  1020.         case RX_STATE:
  1021.           if (RSSIInitState == RX_STATE) {
  1022.             atomic usRSSIVal = data;
  1023.           }
  1024.           RSSIInitState = NULL_STATE;
  1025.           break;
  1026.         case PRETX_STATE:
  1027.           iRSSIcount++;
  1028.           // if the channel is clear or CCA is disabled, GO GO GO!
  1029.           if (((data > (usSquelchVal + CC1K_SquelchBuffer)) || (!bCCAEnable)) && (RSSIInitState == PRETX_STATE)) { 
  1030.             call SpiByteFifo.writeByte(0xaa);
  1031.             call CC1000Control.TxMode();
  1032.             call SpiByteFifo.txMode();
  1033.             usRSSIVal = data;
  1034.             iRSSIcount = CC1K_MaxRSSISamples;
  1035.             bRSSIValid = TRUE;
  1036.             TxByteCnt = 0;
  1037.             usRunningCRC = 0;
  1038.             RadioState = TX_STATE;
  1039.             RadioTxState = TXSTATE_PREAMBLE;
  1040.             NextTxByte = 0xaa;
  1041.             RSSIInitState = NULL_STATE;
  1042.           }
  1043.           else {
  1044.             RSSIInitState = NULL_STATE;
  1045.             if (iRSSIcount == CC1K_MaxRSSISamples) {
  1046.               sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
  1047.               RadioState = IDLE_STATE;
  1048.             }
  1049.             else {
  1050.               RSSIInitState = currentRadioState;
  1051.               call RSSIADC.getData();
  1052.             }
  1053.           }
  1054.           break;
  1055.         case PULSE_CHECK_STATE:
  1056.           atomic{
  1057.             uint8_t done = 0;
  1058.             uint16_t threshold = call GetSquelch();
  1059.             threshold = threshold - (call GetSquelch() >> 2);
  1060.             if(data > threshold){
  1061.               // adjust the noise floor level
  1062.               atomic usTempSquelch = data;
  1063.               post adjustSquelch();
  1064.             }else if(pulse_check_count > 5){
  1065.               //go to the idle state since no outliers were found
  1066.               call CC1000Control.RxMode();
  1067.               RadioState = IDLE_STATE;
  1068.               call SpiByteFifo.rxMode();     // SPI to miso
  1069.               call SpiByteFifo.enableIntr(); // enable spi interrupt
  1070.               post IdleTimerTask();
  1071.               done = 1;
  1072.             }else {
  1073.               call CC1000Control.RxMode();
  1074.               if(call RSSIADC.getData()){
  1075.                 TOSH_uwait(80);
  1076.                 pulse_check_count ++;
  1077.                 done = 1;
  1078.               }
  1079.               pulse_check_sum ++;
  1080.               call CC1000StdControl.stop();
  1081.             }
  1082.             if (bTxPending) { // bug fixed by Dr. Rhee
  1083.               //go to the idle state since no outliers were found
  1084.               call CC1000Control.RxMode();
  1085.               RadioState = IDLE_STATE;
  1086.               call SpiByteFifo.rxMode();     // SPI to miso
  1087.               call SpiByteFifo.enableIntr(); // enable spi interrupt
  1088.               post IdleTimerTask();
  1089.               done = 1;
  1090.             }
  1091.             if(done == 0){
  1092.               post SleepTimerTask();
  1093.               RadioState = POWER_DOWN_STATE;
  1094.               call SpiByteFifo.disableIntr();
  1095.             }
  1096.           }
  1097.           //go to the power down state
  1098.           break;
  1099.         default:
  1100.         }
  1101.       }
  1102.     return SUCCESS;
  1103.   }
  1104.   // XXX:JP- for testing the mac layer squlech value
  1105.   async command uint16_t GetSquelch() {
  1106.     return usSquelchVal;
  1107.   }
  1108.   // XXX:JP- for testing the mac layer power consumption
  1109.   async command uint16_t GetPower() {
  1110.     return power_sum;
  1111.   }
  1112.   async command uint16_t GetDataSent() {
  1113.     return dataSent;
  1114.   }
  1115.   async command result_t ResetDataSent() {
  1116.     dataSent = 0;
  1117.     return SUCCESS;
  1118.   }
  1119.   async command uint16_t GetPower_tx() {
  1120.     return tx_sum;
  1121.   }
  1122.   async command uint16_t GetPower_rx() {
  1123.     return rx_sum;
  1124.   }
  1125.   async command uint16_t GetPower_sp() {
  1126.     return sp_sum;
  1127.   }
  1128.   async command result_t ResetPower() {
  1129.     power_sum = 0;
  1130.     pulse_check_sum = 0;
  1131.     send_sum = 0;
  1132.     receive_sum = 0;
  1133.     sp_sum = 0;
  1134.     tx_sum = 0;
  1135.     rx_sum = 0;
  1136.     return SUCCESS;
  1137.   }
  1138.   async command result_t MacControl.enableAck() {
  1139.     atomic bAckEnable = TRUE;
  1140.     return SUCCESS;
  1141.   }
  1142.   async command result_t MacControl.disableAck() {
  1143.     atomic bAckEnable = FALSE;
  1144.     return SUCCESS;
  1145.   }
  1146.   async command result_t MacControl.enableCCA() {
  1147.     atomic bCCAEnable = TRUE;
  1148.     return SUCCESS;
  1149.   }
  1150.   async command result_t MacControl.disableCCA() {
  1151.     atomic bCCAEnable = TRUE; 
  1152.     return SUCCESS;
  1153.   }
  1154.   // ***Not yet implemented
  1155.   async command TOS_MsgPtr MacControl.HaltTx() {
  1156.     return 0;
  1157.   }
  1158.   // Default events for radio send/receive coordinators do nothing.
  1159.   // Be very careful using these, you'll break the stack.
  1160.   default async event void RadioSendCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset, TOS_MsgPtr msgBuff) { }
  1161.   default async event void RadioSendCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  1162.   default async event void RadioSendCoordinator.blockTimer() { }
  1163.   default async event void RadioReceiveCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset, TOS_MsgPtr msgBuff) { }
  1164.   default async event void RadioReceiveCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  1165.   default async event void RadioReceiveCoordinator.blockTimer() { }
  1166.   default async event int16_t MacBackoff.initialBackoff(TOS_MsgPtr m) { 
  1167.     return (call Random.rand() & 0x1F) + 1;
  1168.   }
  1169.   default async event int16_t MacBackoff.congestionBackoff(TOS_MsgPtr m) { 
  1170.     return (call Random.rand() & 0xF) + 1;
  1171.   }
  1172. }