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

网络

开发平台:

Others

  1. // $Id: CC1000RadioIntM.nc,v 1.1.1.1 2005/04/22 04:26:45 acwarrie Exp $
  2. /* tab:4
  3.  * "Copyright (c) 2000-2003 The Regents of the University  of California.  
  4.  * All rights reserved.
  5.  *
  6.  * Permission to use, copy, modify, and distribute this software and its
  7.  * documentation for any purpose, without fee, and without written agreement is
  8.  * hereby granted, provided that the above copyright notice, the following
  9.  * two paragraphs and the author appear in all copies of this software.
  10.  * 
  11.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
  12.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  13.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  14.  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  15.  * 
  16.  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
  17.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  18.  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  19.  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
  20.  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
  21.  *
  22.  * Copyright (c) 2002-2003 Intel Corporation
  23.  * All rights reserved.
  24.  *
  25.  * This file is distributed under the terms in the attached INTEL-LICENSE     
  26.  * file. If you do not find these files, copies can be found by writing to
  27.  * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, 
  28.  * 94704.  Attention:  Intel License Inquiry.
  29.  */
  30. /*  
  31.  *  Authors: Philip Buonadonna, Jaein Jeong, Joe Polastre, Chris Karlof
  32.  *  Date last modified: $Revision: 1.1.1.1 $
  33.  *
  34.  * This module provides the layer2 functionality for the mica2 radio.
  35.  * While the internal architecture of this module is not CC1000 specific,
  36.  * It does make some CC1000 specific calls via CC1000Control.
  37.  *
  38.  *
  39.  * This makes use of TinySec. WARNING: Beware of using RadioCoordinators
  40.  * with this stack. Length and group byte are switched.
  41.  * 
  42.  * $Id: CC1000RadioIntM.nc,v 1.1.1.1 2005/04/22 04:26:45 acwarrie Exp $
  43.  */
  44. /**
  45.  * @author Philip Buonadonna
  46.  * @author Jaein Jeong
  47.  * @author Joe Polastre
  48.  * @author Chris Karlof
  49.  */
  50.   
  51. includes crc;
  52. includes CC1000Const;
  53. module CC1000RadioIntM {
  54.   provides {
  55.     interface StdControl;
  56.     interface BareSendMsg as Send;
  57.     interface ReceiveMsg as Receive;
  58.     command result_t EnableRSSI();
  59.     command result_t DisableRSSI();
  60.     command result_t SetListeningMode(uint8_t power);
  61.     command uint8_t GetListeningMode();
  62.     command result_t SetTransmitMode(uint8_t power);
  63.     command uint8_t GetTransmitMode();
  64.     command uint16_t GetSquelch();
  65.     interface RadioCoordinator as RadioSendCoordinator;
  66.     interface RadioCoordinator as RadioReceiveCoordinator;
  67.     interface TinySecRadio;
  68.   }
  69.   uses {
  70.     interface PowerManagement;
  71.     interface StdControl as CC1000StdControl;
  72.     interface CC1000Control;
  73.     interface Random;
  74.     interface ADCControl;
  75.     interface ADC as RSSIADC;
  76.     interface SpiByteFifo;
  77.     interface StdControl as TimerControl;
  78.     interface Timer as WakeupTimer;
  79.     interface Timer as SquelchTimer;
  80.     // TinySec
  81.     interface TinySec;
  82.     interface Leds;
  83.   }
  84. }
  85. implementation {
  86.   enum {
  87.     TX_STATE,
  88.     DISABLED_STATE,
  89.     IDLE_STATE,
  90.     PRETX_STATE,
  91.     SYNC_STATE,
  92.     HEADER_RX_STATE,
  93.     RX_STATE,
  94.     RX_STATE_TINYSEC,
  95.     SENDING_ACK,
  96.     POWER_DOWN_STATE,
  97.   };
  98.   enum {
  99.     TXSTATE_WAIT,
  100.     TXSTATE_START,
  101.     TXSTATE_PREAMBLE,
  102.     TXSTATE_SYNC,
  103.     TXSTATE_DATA,
  104.     TXSTATE_DATA_TINYSEC,
  105.     TXSTATE_CRC,
  106.     TXSTATE_FLUSH,
  107.     TXSTATE_WAIT_FOR_ACK,
  108.     TXSTATE_READ_ACK,
  109.     TXSTATE_DONE
  110.   };
  111.   enum {
  112.     SYNC_BYTE = 0x33,
  113.     NSYNC_BYTE = 0xcc,
  114.     SYNC_WORD = 0x33cc,
  115.     NSYNC_WORD = 0xcc33,
  116.     ACK_LENGTH = 16,
  117.     MAX_ACK_WAIT = 18
  118.   };
  119.   uint8_t ack_code[3] = {0xab, 0xba, 0x83};
  120.   uint8_t RadioState;
  121.   uint8_t RadioTxState;
  122.   norace uint8_t iRSSIcount;
  123.   uint8_t iSquelchCount;
  124.   uint16_t txlength;
  125.   uint16_t rxlength;
  126.   /**** TinySec ****/
  127.   TOS_Msg_TinySecCompat* txbufptr;  // pointer to transmit buffer
  128.   TOS_Msg_TinySecCompat* rxbufptr;  // pointer to receive buffer
  129.   TOS_Msg_TinySecCompat RxBuf; // save received messages
  130.   /**** TinySec ****/
  131.   uint8_t NextTxByte;
  132.   uint8_t lplpower;        //  low power listening mode
  133.   uint8_t lplpowertx;      //  low power listening transmit mode
  134.   uint16_t preamblelen;    //  current length of the preamble
  135.  
  136.   uint16_t PreambleCount;   //  found a valid preamble
  137.   uint8_t SOFCount;
  138.   uint16_t search_word;
  139.   union {
  140.     uint16_t W;
  141.     struct {
  142.       uint8_t LSB;
  143.       uint8_t MSB;
  144.     };
  145.   } RxShiftBuf;
  146.   uint8_t RxBitOffset; // bit offset for spibus
  147.   uint16_t RxByteCnt; // received byte counter
  148.   uint16_t TxByteCnt;
  149.   uint16_t RSSISampleFreq; // in Bytes rcvd per sample
  150.   norace bool bInvertRxData; // data inverted
  151.   bool bTxPending;
  152.   bool bTxBusy;
  153.   bool bRSSIValid;
  154.   uint16_t usRunningCRC; // Running CRC variable
  155.   norace uint16_t usRSSIVal; // suppress nesc warnings
  156.   uint16_t usSquelchVal;
  157.   uint16_t usTempSquelch;
  158.   uint8_t usSquelchIndex;
  159.   uint16_t usSquelchTable[CC1K_SquelchTableSize];
  160.   int16_t sMacDelay;    // MAC delay for the next transmission
  161.   // XXX-PB:
  162.   // Here's the deal, the mica (RFM) radio stacks used TOS_LOCAL_ADDRESS
  163.   // to determine if an L2 ack was reqd.  This stack doesn't do L2 acks
  164.   // and, thus doesn't need it.  HOWEVER, some set-mote-id versions
  165.   // break if this symbol is missing from the binary.
  166.   // Thus, I put this LocalAddr here and set it to TOS_LOCAL_ADDRESS
  167.   // to keep things happy for now.
  168.   volatile uint16_t LocalAddr;
  169.   ///**********************************************************
  170.   //* local function definitions
  171.   //**********************************************************/
  172. /*
  173.   int sortByShort(const void *x, const void *y) {
  174.     uint16_t* x1 = (uint16_t*)x;
  175.     uint16_t* y1 = (uint16_t*)y;
  176.     if (x1[0] > y1[0]) return -1;
  177.     if (x1[0] == y1[0]) return 0;
  178.     if (x1[0] < y1[0]) return 1;
  179.     return 0; // shouldn't reach here becasue it covers all the cases
  180.   }
  181. */
  182.   task void adjustSquelch() {
  183.     uint16_t tempArray[CC1K_SquelchTableSize];
  184.     char i,j,min; 
  185.     uint16_t min_value;
  186.     atomic {
  187.       usSquelchTable[usSquelchIndex] = usTempSquelch;
  188.       usSquelchIndex++;
  189.       if (usSquelchIndex >= CC1K_SquelchTableSize)
  190.         usSquelchIndex = 0;
  191.       if (iSquelchCount <= CC1K_SquelchCount)
  192.         iSquelchCount++;  
  193.     }
  194.     for (i=0; i<CC1K_SquelchTableSize; i++) {
  195.       tempArray[(int)i] = usSquelchTable[(int)i];
  196.     }
  197.     min = 0;
  198.     for (j = 0; j < ((CC1K_SquelchTableSize) >> 1); j++) {
  199.       for (i = 1; i < CC1K_SquelchTableSize; i++) {
  200.         if ((tempArray[(int)i] != 0xFFFF) && 
  201.             (tempArray[(int)i] < tempArray[(int)min])) {
  202.           min = i;
  203.         }
  204.       }
  205.       min_value = tempArray[(int)min];
  206.       tempArray[(int)min] = 0xFFFF;
  207.     }
  208.     atomic usSquelchVal = ((usSquelchVal << 4) + (min_value << 1)) / 18;
  209.     /*
  210.     // XXX: qsort actually causes ~600bits/sec lower bandwidth... why???
  211.     //
  212.     qsort (tempArray,CC1K_SquelchTableSize, sizeof(uint16_t),sortByShort);
  213.     min_value = tempArray[CC1K_SquelchTableSize >> 1];
  214.     atomic usSquelchVal = ((usSquelchVal << 4) + (min_value << 1)) / 18;
  215.     */
  216.   }
  217.   /**** TinySec ****/
  218.   void swapLengthAndGroup(TOS_Msg* buf) {
  219.     uint8_t tmp = buf->group;
  220.     ((TOS_Msg_TinySecCompat*) buf)->length = buf->length;
  221.     ((TOS_Msg_TinySecCompat*) buf)->group = tmp;
  222.   }
  223.   /**** TinySec ****/
  224.   
  225.   task void PacketRcvd() {
  226.     TOS_MsgPtr pBuf;
  227.     atomic {
  228.       rxbufptr->time = 0;
  229.       /**** TinySec ****/
  230.       pBuf = (TOS_MsgPtr) rxbufptr;
  231.       swapLengthAndGroup(pBuf);
  232.       /**** TinySec ****/
  233.       // EWMA to determin squelch values
  234.       usSquelchVal = (((5*pBuf->strength) + (3*usSquelchVal)) >> 3);
  235.     }
  236.     pBuf = signal Receive.receive((TOS_MsgPtr)pBuf);
  237.     atomic {
  238.       if (pBuf) 
  239. rxbufptr = (TOS_Msg_TinySecCompat*) pBuf;
  240.       rxbufptr->length = 0;
  241.     }
  242.     call SpiByteFifo.enableIntr();
  243.   }
  244.   
  245.   task void PacketSent() {
  246.     TOS_MsgPtr pBuf; //store buf on stack 
  247.     atomic {
  248.       txbufptr->time = 0;
  249.       pBuf = (TOS_Msg*) txbufptr;
  250.       /**** TinySec ****/
  251.       swapLengthAndGroup(pBuf);
  252.       /**** TinySec ****/
  253.     }
  254.     signal Send.sendDone((TOS_MsgPtr)pBuf,SUCCESS);
  255.     atomic bTxBusy = FALSE;
  256.   }
  257.   ///**********************************************************
  258.   //* Exported interface functions
  259.   //**********************************************************/
  260.   
  261.   command result_t StdControl.init() {
  262.     char i;
  263.     atomic {
  264.       RadioState = DISABLED_STATE;
  265.       RadioTxState = TXSTATE_PREAMBLE;
  266.       rxbufptr = &RxBuf;
  267.       rxbufptr->length = 0;
  268.       rxlength = TINYSEC_MSG_DATA_SIZE-TINYSEC_MAC_LENGTH;
  269.       RxBitOffset = 0;
  270.       iSquelchCount = 0;
  271.       
  272.       PreambleCount = 0;
  273.       RSSISampleFreq = 0;
  274.       RxShiftBuf.W = 0;
  275.       iRSSIcount = 0;
  276.       bTxPending = FALSE;
  277.       bTxBusy = FALSE;
  278.       bRSSIValid = FALSE;
  279.       sMacDelay = -1;
  280.       usRSSIVal = -1;
  281.       usSquelchIndex = 0;
  282.       lplpower = lplpowertx = 0;
  283.       usSquelchVal = CC1K_SquelchInit;
  284.     }
  285.     for (i = 0; i < CC1K_SquelchTableSize; i++)
  286.       usSquelchTable[(int)i] = CC1K_SquelchInit;
  287.     call SpiByteFifo.initSlave(); // set spi bus to slave mode
  288.     call CC1000StdControl.init();
  289.     call CC1000Control.SelectLock(0x9); // Select MANCHESTER VIOLATION
  290.     bInvertRxData = call CC1000Control.GetLOStatus();
  291.     call ADCControl.bindPort(TOS_ADC_CC_RSSI_PORT,TOSH_ACTUAL_CC_RSSI_PORT);
  292.     call ADCControl.init();
  293.     call Random.init();
  294.     call TimerControl.init();
  295.     LocalAddr = TOS_LOCAL_ADDRESS;
  296.     return SUCCESS;
  297.   }
  298.   
  299.   command result_t EnableRSSI() {
  300.     return SUCCESS;
  301.   }
  302.   command result_t DisableRSSI() {
  303.     return SUCCESS;
  304.   }
  305.   command uint8_t GetTransmitMode() {
  306.     return lplpowertx;
  307.   }
  308.   /**
  309.    * Set the state of low power transmit on the chipcon radio.
  310.    * The transmit mode of the sender *must* match the receiver in
  311.    * order for the receiver to successfully get the packet.
  312.    * <p>
  313.    * The default power up state is 0 (radio always on).
  314.    * See CC1000Const.h for low power duty cycles and bandwidth
  315.    */
  316.   command result_t SetTransmitMode(uint8_t power) {
  317.     if ((power >= CC1K_LPL_STATES) || (power == lplpowertx))
  318.       return FAIL;
  319.     // check if the radio is currently doing something
  320.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  321.   (RadioState == IDLE_STATE) ||
  322.   (RadioState == DISABLED_STATE))) {
  323.       atomic {
  324. lplpowertx = power;
  325. preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8)
  326.                        | PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  327.       }
  328.       return SUCCESS;
  329.     }
  330.     return FAIL;
  331.   }
  332.   /**
  333.    * Set the state of low power listening on the chipcon radio.
  334.    * <p>
  335.    * The default power up state is 0 (radio always on).
  336.    * See CC1000Const.h for low power duty cycles and bandwidth
  337.    */
  338.   command result_t SetListeningMode(uint8_t power) {
  339.     // valid low power listening values are 0 to 3
  340.     // 0 is "always on" and 3 is lowest duty cycle
  341.     // 1 and 2 are in the middle
  342.     if ((power >= CC1K_LPL_STATES) || (power == lplpower))
  343.       return FAIL;
  344.     // check if the radio is currently doing something
  345.     if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || 
  346.   (RadioState == IDLE_STATE) ||
  347.   (RadioState == DISABLED_STATE))) {
  348.       // change receiving function in CC1000Radio
  349.       call WakeupTimer.stop();
  350.       atomic {
  351. if (lplpower == lplpowertx) {
  352.   lplpowertx = power;
  353. }
  354. lplpower = power;
  355.       }
  356.       // if successful, change power here
  357.       if (RadioState == IDLE_STATE) {
  358. RadioState = DISABLED_STATE;
  359. call StdControl.stop();
  360. call StdControl.start();
  361.       }
  362.       if (RadioState == POWER_DOWN_STATE) {
  363. RadioState = DISABLED_STATE;
  364. call StdControl.start();
  365. call PowerManagement.adjustPower();
  366.       }
  367.     }
  368.     else {
  369.       return FAIL;
  370.     }
  371.     return SUCCESS;
  372.   }
  373.   /**
  374.    * Gets the state of low power listening on the chipcon radio.
  375.    * <p>
  376.    * @return Current low power listening state value
  377.    */
  378.   command uint8_t GetListeningMode() {
  379.     return lplpower;
  380.   } 
  381.   event result_t SquelchTimer.fired() {
  382.     char currentRadioState;
  383.     atomic currentRadioState = RadioState;
  384.     if (currentRadioState == IDLE_STATE)
  385.       call RSSIADC.getData();
  386.     return SUCCESS;
  387.   }
  388.   event result_t WakeupTimer.fired() {
  389.     uint16_t sleeptime;
  390.     bool tempTxPending;
  391.     uint8_t currentRadioState;
  392.     if (lplpower == 0)
  393.       return SUCCESS;
  394.     atomic {
  395.       currentRadioState = RadioState;
  396.       tempTxPending = bTxPending;
  397.     }
  398.     switch(currentRadioState) {
  399.     case IDLE_STATE:
  400.       sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) |
  401.    PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1]));
  402.       if (!tempTxPending) {
  403.         atomic RadioState = POWER_DOWN_STATE;
  404.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  405.         call SquelchTimer.stop();
  406.         call CC1000StdControl.stop();
  407. call SpiByteFifo.disableIntr();
  408.       }
  409.       else {
  410.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
  411.       }
  412.       break;
  413.     case POWER_DOWN_STATE:
  414.       sleeptime = PRG_RDB(&CC1K_LPL_SleepPreamble[lplpower]);
  415.       atomic RadioState = IDLE_STATE;
  416.       call CC1000StdControl.start();
  417.       call CC1000Control.BIASOn();
  418.       call SpiByteFifo.rxMode(); // SPI to miso
  419.       call CC1000Control.RxMode();
  420.       call SpiByteFifo.enableIntr(); // enable spi interrupt
  421.       if (iSquelchCount > CC1K_SquelchCount)
  422.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  423.       else
  424.         call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  425.       call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  426.       break;
  427.     default:
  428.       call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
  429.     }
  430.     return SUCCESS;
  431.   }
  432.   command result_t StdControl.stop() {
  433.     atomic RadioState = DISABLED_STATE;
  434.     call SquelchTimer.stop();
  435.     call WakeupTimer.stop();
  436.     call CC1000StdControl.stop();
  437.     call SpiByteFifo.disableIntr(); // disable spi interrupt
  438.     return SUCCESS;
  439.   }
  440.   command result_t StdControl.start() {
  441.     uint8_t currentRadioState;
  442.     atomic currentRadioState = RadioState;
  443.     if (currentRadioState == DISABLED_STATE) {
  444.       atomic {
  445.         rxbufptr->length = 0;
  446.         RadioState  = IDLE_STATE;
  447.         bTxPending = bTxBusy = FALSE;
  448.         sMacDelay = -1;
  449.         preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) |
  450.      PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
  451.       }
  452.       if (lplpower == 0) {
  453.         // all power on, captain!
  454.         rxbufptr->length = 0;
  455.         atomic RadioState = IDLE_STATE;
  456.         call CC1000StdControl.start();
  457.         call CC1000Control.BIASOn();
  458.         call SpiByteFifo.rxMode(); // SPI to miso
  459.         call CC1000Control.RxMode();
  460.         if (iSquelchCount > CC1K_SquelchCount)
  461.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  462.         else
  463.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  464.         call SpiByteFifo.enableIntr(); // enable spi interrupt
  465.       }
  466.       else {
  467.         uint16_t sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) |
  468.                       PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1]));
  469.         atomic RadioState = POWER_DOWN_STATE;
  470.         call TimerControl.start();
  471.         call SquelchTimer.stop();
  472.         call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
  473.       }
  474.     }
  475.     return SUCCESS;
  476.   }
  477.   /*** TinySec ****/
  478.   async event result_t TinySec.sendDone(result_t result) {
  479.     atomic {
  480.       TxByteCnt = 0;
  481.       RadioTxState = TXSTATE_FLUSH;
  482.     }
  483.     return result;
  484.   }
  485.   async event result_t TinySec.receiveInitDone(result_t result, uint16_t length,
  486.        bool ts_enabled) {
  487.     atomic {
  488.       rxlength = length;
  489.       if(result == SUCCESS) {
  490.         if(ts_enabled)
  491.           RadioState = RX_STATE_TINYSEC;
  492.         else
  493.           RadioState = RX_STATE;
  494.       } else {
  495.         rxbufptr->length = 0;
  496.         RadioState = IDLE_STATE;
  497.       }
  498.     }
  499.     return SUCCESS;
  500.   }
  501.   async event result_t TinySec.receiveDone(result_t result) {
  502.     rxbufptr->strength = usRSSIVal;
  503.     if(rxbufptr->crc == 1 &&
  504.        (rxbufptr->addr == TOS_LOCAL_ADDRESS
  505. || rxbufptr->addr == TOS_BCAST_ADDR)){
  506.       //call Leds.redToggle();
  507.       RadioState = SENDING_ACK; 
  508.       call CC1000Control.TxMode();
  509.       call SpiByteFifo.txMode();
  510.       call SpiByteFifo.writeByte(0xaa);
  511.       RxByteCnt = 0;
  512.       return SUCCESS; 
  513.     } else {
  514.       call SpiByteFifo.disableIntr();
  515.       RadioState = IDLE_STATE; //DISABLED_STATE;
  516.       if (!(post PacketRcvd())) {
  517. // If there are insufficient resources to process the incoming packet
  518. // we drop it
  519. rxbufptr->length = 0;
  520. RadioState = IDLE_STATE;
  521. call SpiByteFifo.enableIntr();
  522.       }
  523.     }
  524.     return SUCCESS;
  525.   }
  526.   /**** TinySec ****/
  527.   
  528.   command result_t Send.send(TOS_MsgPtr pMsg) {
  529.     result_t Result = SUCCESS;
  530.     uint8_t currentRadioState = 0;
  531.     atomic {
  532.       if (bTxBusy) {
  533. Result = FAIL;
  534.       }
  535.       else {
  536. bTxBusy = TRUE;
  537.         /**** TinySec ****/
  538.         // swap TOS_Msg into TOS_Msg_TinySecCompat
  539.         // don't reference pMsg after here
  540.         swapLengthAndGroup(pMsg);
  541. txbufptr = (TOS_Msg_TinySecCompat*) pMsg;
  542.         /**** TinySec ****/
  543.         // initially back off [1,32] bytes (approx 2/3 packet)
  544.         sMacDelay = (call Random.rand() & 0x1F) + 1;
  545. bTxPending = TRUE;
  546.         /****** TinySec *****/
  547. // bad form to call a command in atomic, but sendInit is short.
  548. // easiest way to lock txbufptr
  549. if(txbufptr->length & TINYSEC_ENABLED_BIT) {
  550.   txlength = call TinySec.sendInit(txbufptr);
  551. } else {
  552.   txlength = txbufptr->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
  553. }
  554.         /****** TinySec *****/
  555.       }
  556.       currentRadioState = RadioState;
  557.     }
  558.     if (Result) {
  559.       // if we're off, start the radio
  560.       if (currentRadioState == POWER_DOWN_STATE) {
  561.         // disable wakeup timer
  562.         call WakeupTimer.stop();
  563.         call CC1000StdControl.start();
  564.         call CC1000Control.BIASOn();
  565.         call CC1000Control.RxMode();
  566.         call SpiByteFifo.rxMode(); // SPI to miso
  567.         call SpiByteFifo.enableIntr(); // enable spi interrupt
  568.         if (iSquelchCount > CC1K_SquelchCount)
  569.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
  570.         else
  571.           call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
  572.         call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
  573.         atomic RadioState = IDLE_STATE;
  574.       }
  575.     }
  576.     return Result;
  577.   }
  578.   
  579.   /**********************************************************
  580.    * make a spibus interrupt handler
  581.    * needs to handle interrupts for transmit delay
  582.    * and then go into byte transmit mode with
  583.    *   timer1 baudrate delay as interrupt handler
  584.    * else
  585.    * needs to handle interrupts for byte read and detect preamble
  586.    *  then handle reading a packet
  587.    * PB - We can use this interrupt handler as a transmit scheduler
  588.    * because the CC1000 continuously clocks in data, regarless
  589.    * of whether it's good or not.  Thus, this routine will be called
  590.    * on every 8 ticks of DCLK. 
  591.    **********************************************************/
  592.   async event result_t SpiByteFifo.dataReady(uint8_t data_in) {
  593.     
  594.     signal RadioSendCoordinator.blockTimer();
  595.     signal RadioReceiveCoordinator.blockTimer();
  596.     if (bInvertRxData) 
  597.       data_in = ~data_in;
  598. #ifdef ENABLE_UART_DEBUG
  599.     UARTPutChar(RadioState);
  600. #endif
  601.     switch (RadioState) {
  602.     case TX_STATE:
  603.       {
  604. call SpiByteFifo.writeByte(NextTxByte);
  605. TxByteCnt++;
  606. switch (RadioTxState) {
  607. case TXSTATE_PREAMBLE:
  608.   if (!(TxByteCnt < preamblelen)) {
  609.     NextTxByte = SYNC_BYTE;
  610.     RadioTxState = TXSTATE_SYNC;
  611.   }
  612.   break;
  613. case TXSTATE_SYNC:
  614.   NextTxByte = NSYNC_BYTE;
  615.           /**** TinySec ****/
  616.           if(txbufptr->length & TINYSEC_ENABLED_BIT)
  617.             RadioTxState = TXSTATE_DATA_TINYSEC;
  618.           else
  619.             RadioTxState = TXSTATE_DATA;
  620.           /**** TinySec ****/
  621.   TxByteCnt = -1;
  622.           // for Time Sync services
  623.   signal RadioSendCoordinator.startSymbol(8, 0,(TOS_MsgPtr) txbufptr); 
  624.   break;
  625. case TXSTATE_DATA:
  626.   if ((uint8_t)(TxByteCnt) < txlength) {
  627.     NextTxByte = ((uint8_t *)txbufptr)[(TxByteCnt)];
  628.     usRunningCRC = crcByte(usRunningCRC,NextTxByte);
  629.     signal RadioSendCoordinator.byte((TOS_MsgPtr) txbufptr,
  630.      (uint8_t)TxByteCnt); // Time Sync
  631.   }
  632.   else {
  633.     NextTxByte = (uint8_t)(usRunningCRC);
  634.     RadioTxState = TXSTATE_CRC;
  635.   }
  636.   break;
  637.           /**** TinySec ****/
  638. case TXSTATE_DATA_TINYSEC:
  639.           signal RadioSendCoordinator.byte((TOS_MsgPtr) txbufptr,
  640.    (uint8_t)TxByteCnt); // Time Sync
  641.           NextTxByte = signal TinySecRadio.getTransmitByte();
  642.   break;
  643.           /**** TinySec ****/
  644.                   
  645. case TXSTATE_CRC:
  646.   NextTxByte = (uint8_t)(usRunningCRC>>8);
  647.   RadioTxState = TXSTATE_FLUSH;
  648.   TxByteCnt = 0;
  649.   break;
  650. case TXSTATE_FLUSH:
  651.   if (TxByteCnt > 3) {
  652.     TxByteCnt = 0;
  653.     RadioTxState = TXSTATE_WAIT_FOR_ACK;
  654.   }
  655.   break;
  656.         case TXSTATE_WAIT_FOR_ACK:
  657.   if(TxByteCnt == 1){
  658. call SpiByteFifo.rxMode();
  659.         call CC1000Control.RxMode();
  660.   }
  661.   if (TxByteCnt > 3) {
  662.     RadioTxState = TXSTATE_READ_ACK;
  663.     TxByteCnt = 0;
  664.     search_word = 0;
  665.   }
  666.   break;
  667.         case TXSTATE_READ_ACK:
  668.   {
  669.      uint8_t i;
  670.      for(i = 0; i < 8; i ++){
  671. search_word <<= 1;
  672.          if(data_in & 0x80) search_word |=  0x1;
  673.          data_in <<= 1;
  674.          if (search_word == 0xba83){
  675.                  txbufptr->ack = 1;
  676.      RadioTxState = TXSTATE_DONE;
  677.                  return SUCCESS;
  678.          }
  679.              }
  680.      }
  681.   if(TxByteCnt == MAX_ACK_WAIT){
  682. txbufptr->ack = 0;
  683.      RadioTxState = TXSTATE_DONE;
  684.   }
  685.   break;
  686. case TXSTATE_DONE:
  687. default:
  688.           call RSSIADC.getData();
  689.   bTxPending = FALSE;
  690.   if (post PacketSent()) {
  691.     // If the post operation succeeds, goto Idle
  692.     // otherwise, we'll try again.
  693.     RadioState = IDLE_STATE;
  694.   }
  695.   break;
  696. }
  697.       }
  698.       break;
  699.     case DISABLED_STATE:
  700.       break;
  701.     case IDLE_STATE: 
  702.       {
  703. if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  704.   PreambleCount++;
  705.   if (PreambleCount > CC1K_ValidPrecursor) {
  706.     PreambleCount = SOFCount = 0;
  707.     RxBitOffset = RxByteCnt = 0;
  708.     usRunningCRC = 0;
  709.     rxlength = MSG_DATA_SIZE-2;
  710.             /**** TinySec ****/
  711.             call TinySec.receiveInit(rxbufptr);
  712.             /**** TinySec ****/
  713.     RadioState = SYNC_STATE;
  714.   }
  715. }
  716. else if (bTxPending && (--sMacDelay <= 0)) {
  717.   bRSSIValid = FALSE;
  718.   RadioState = PRETX_STATE;
  719.           iRSSIcount = 0;
  720.   PreambleCount = 0;
  721.   call RSSIADC.getData();
  722. }
  723.       }
  724.       break;
  725.     case PRETX_STATE:
  726.       {
  727. if (((data_in == (0xaa)) || (data_in == (0x55)))) {
  728.   // Back to the penalty box.
  729.           sMacDelay = (call Random.rand() & 0xF) + 1;
  730.   RadioState = IDLE_STATE;
  731. }
  732. /*
  733. else if (bRSSIValid) {
  734.   if (usRSSIVal > (usSquelchVal + CC1K_SquelchBuffer)) { 
  735.     // ROCK AND ROLL!!!!!
  736.     call CC1000Control.TxMode();
  737.     call SpiByteFifo.txMode();
  738.     TxByteCnt = 0;
  739.     usRunningCRC = 0;
  740.     RadioState = TX_STATE;
  741.     RadioTxState = TXSTATE_PREAMBLE;
  742.     NextTxByte = 0xaa;
  743.     call SpiByteFifo.writeByte(0xaa);
  744.   }
  745.   else {
  746.     // Russin frussin freakin frick o frack
  747.             sMacDelay = (call Random.rand() & 0xF) + 1;
  748.     RadioState = IDLE_STATE;
  749.   }
  750. }
  751. */
  752.       }
  753.       break;
  754.     case SYNC_STATE:
  755.       {
  756. // draw in the preamble bytes and look for a sync byte
  757. // save the data in a short with last byte received as msbyte
  758. //    and current byte received as the lsbyte.
  759. // use a bit shift compare to find the byte boundary for the sync byte
  760. // retain the shift value and use it to collect all of the packet data
  761. // check for data inversion, and restore proper polarity 
  762.         // XXX-PB: Don't do this.
  763. uint8_t i;
  764. if ((data_in == 0xaa) || (data_in == 0x55)) {
  765.   // It is actually possible to have the LAST BIT of the incoming
  766.   // data be part of the Sync Byte.  SO, we need to store that
  767.   // However, the next byte should definitely not have this pattern.
  768.   // XXX-PB: Do we need to check for excessive preamble?
  769.   RxShiftBuf.MSB = data_in;
  770. }
  771. else {
  772.   // TODO: Modify to be tolerant of bad bits in the preamble...
  773.   uint16_t usTmp;
  774.   switch (SOFCount) {
  775.   case 0:
  776.     RxShiftBuf.LSB = data_in;
  777.     break;
  778.   
  779.   case 1:
  780.   case 2: 
  781.     // bit shift the data in with previous sample to find sync
  782.     usTmp = RxShiftBuf.W;
  783.     RxShiftBuf.W <<= 8;
  784.     RxShiftBuf.LSB = data_in;
  785.     for(i=0;i<8;i++) {
  786.       usTmp <<= 1;
  787.       if(data_in & 0x80)
  788. usTmp  |=  0x1;
  789.       data_in <<= 1;
  790.       // check for sync bytes
  791.       if (usTmp == SYNC_WORD) {
  792.                 if (rxbufptr->length !=0) {
  793.                   call Leds.redToggle();
  794.                   RadioState = IDLE_STATE;
  795.                 }
  796.                 else {
  797.                   RadioState = HEADER_RX_STATE;
  798.                   call RSSIADC.getData();
  799.                   RxBitOffset = 7-i;
  800.   // For time sync services
  801.                   signal RadioReceiveCoordinator.startSymbol(8, RxBitOffset,
  802.      (TOS_MsgPtr) rxbufptr);
  803.                 }
  804. break;
  805.       }
  806.     }
  807.     break;
  808.   default:
  809.     // We didn't find it after a reasonable number of tries, so....
  810.     RadioState = IDLE_STATE;  // Ensures we wait till the end of the transmission
  811.     break;
  812.   }
  813.   SOFCount++;
  814. }
  815.       }
  816.       break;
  817.       /**** TinySec ****/
  818.     case HEADER_RX_STATE:
  819.       {
  820.    char Byte;
  821.         
  822. RxShiftBuf.W <<=8;
  823. RxShiftBuf.LSB = data_in;
  824.         
  825. Byte = (RxShiftBuf.W >> RxBitOffset);
  826. ((char*)rxbufptr)[(int)RxByteCnt] = Byte;      
  827. RxByteCnt++;
  828. signal RadioReceiveCoordinator.byte((TOS_MsgPtr) rxbufptr,
  829.     (uint8_t)RxByteCnt-1);
  830.         
  831.         usRunningCRC = crcByte(usRunningCRC,Byte);
  832.         signal TinySecRadio.byteReceived(Byte);
  833.         
  834.       }
  835.       break;
  836.       
  837.     case RX_STATE_TINYSEC:
  838.       {
  839. char Byte;
  840. RxShiftBuf.W <<=8;
  841. RxShiftBuf.LSB = data_in;
  842. Byte = (RxShiftBuf.W >> RxBitOffset);
  843. RxByteCnt++;
  844. signal RadioReceiveCoordinator.byte((TOS_MsgPtr) rxbufptr,
  845.     (uint8_t)RxByteCnt-1);
  846.         signal TinySecRadio.byteReceived(Byte);   
  847.       }         
  848.       break;
  849.       /**** TinySec ****/
  850.       
  851.       
  852.       //  collect the data and shift into double buffer
  853.       //  shift out data by correct offset
  854.       //  invert the data if necessary
  855.       //  stop after the correct packet length is read
  856.       //  return notification to upper levels
  857.       //  go back to idle state
  858.     case RX_STATE:
  859.       {
  860. char Byte;
  861. RxShiftBuf.W <<=8;
  862. RxShiftBuf.LSB = data_in;
  863. Byte = (RxShiftBuf.W >> RxBitOffset);
  864. ((char*)rxbufptr)[(int)RxByteCnt] = Byte;
  865. RxByteCnt++;
  866. // Time Sync:  substract one to start counting from zero
  867. signal RadioReceiveCoordinator.byte((TOS_MsgPtr) rxbufptr,
  868.     (uint8_t)RxByteCnt-1);
  869. if (RxByteCnt < rxlength) {
  870.   usRunningCRC = crcByte(usRunningCRC,Byte);
  871. }
  872. else if (RxByteCnt == rxlength) {
  873.   usRunningCRC = crcByte(usRunningCRC,Byte);
  874.   // Shift index ahead to the crc field.
  875.   RxByteCnt = offsetof(struct TOS_Msg,crc);
  876. }
  877. else if (RxByteCnt >= MSG_DATA_SIZE) { 
  878.   // Packet filtering based on bad CRC's is done at higher layers.
  879.   // So sayeth the TOS weenies.
  880.   if (rxbufptr->crc == usRunningCRC) {
  881.     rxbufptr->crc = 1;
  882.     if(rxbufptr->addr == TOS_LOCAL_ADDRESS || rxbufptr->addr == TOS_BCAST_ADDR){
  883.     RadioState = SENDING_ACK; 
  884.     call CC1000Control.TxMode();
  885.     call SpiByteFifo.txMode();
  886.     call SpiByteFifo.writeByte(0xaa);
  887.     RxByteCnt = 0;
  888.     return SUCCESS; 
  889.        }
  890.   } else {
  891.     rxbufptr->crc = 0;
  892.   }
  893.   call SpiByteFifo.disableIntr();
  894.   
  895.   RadioState = IDLE_STATE; //DISABLED_STATE;
  896.   rxbufptr->strength = usRSSIVal;
  897.   if (!(post PacketRcvd())) {
  898.     // If there are insufficient resources to process the incoming packet
  899.     // we drop it
  900.             rxbufptr->length = 0;
  901.     RadioState = IDLE_STATE;
  902.     call SpiByteFifo.enableIntr();
  903.   }
  904. }
  905.       }
  906.       break;
  907.     case SENDING_ACK:
  908.       {
  909. RxByteCnt++;
  910. if (RxByteCnt >= ACK_LENGTH) { 
  911.     call CC1000Control.RxMode();
  912.     call SpiByteFifo.rxMode();
  913.     call SpiByteFifo.disableIntr();
  914.     RadioState = IDLE_STATE; //DISABLED_STATE;
  915.     rxbufptr->strength = usRSSIVal;
  916.     if (!(post PacketRcvd())) {
  917.    rxbufptr->length = 0;
  918.    RadioState = IDLE_STATE;
  919.    call SpiByteFifo.enableIntr();
  920.     }
  921. }else if(RxByteCnt >= ACK_LENGTH - sizeof(ack_code) - 2){
  922.     call SpiByteFifo.writeByte(ack_code[RxByteCnt + sizeof(ack_code) + 2- ACK_LENGTH]);
  923.         }
  924.       }
  925.       break;
  926.   
  927.     default:
  928.       break;
  929.     }
  930.   return SUCCESS;
  931. }
  932. async event result_t RSSIADC.dataReady(uint16_t data) {
  933.   uint8_t currentRadioState;
  934.   atomic currentRadioState = RadioState;
  935.   // find the maximum RSSI value over CC1K_MAX_RSSI_SAMPLES
  936.   switch(currentRadioState) {
  937.   case PRETX_STATE:
  938.     iRSSIcount++;
  939.     // if the channel is clear, GO GO GO!
  940.     if (data > (usSquelchVal + CC1K_SquelchBuffer)) { 
  941.       call SpiByteFifo.writeByte(0xaa);
  942.       call CC1000Control.TxMode();
  943.       call SpiByteFifo.txMode();
  944.       atomic {
  945.         usRSSIVal = data;
  946.         iRSSIcount = CC1K_MaxRSSISamples;
  947.         bRSSIValid = TRUE;
  948.         TxByteCnt = 0;
  949.         usRunningCRC = 0;
  950.         RadioState = TX_STATE;
  951.         RadioTxState = TXSTATE_PREAMBLE;
  952.         NextTxByte = 0xaa;
  953. // start encrypting packet - re-enables interrupts
  954. // check if encrypt enabled bit is set
  955.         /**** TinySec ****/
  956. if(txbufptr->length & TINYSEC_ENABLED_BIT) {
  957.   call TinySec.send();
  958. }
  959.         /**** TinySec ****/
  960.       }
  961.       return SUCCESS;
  962.     }
  963.     if (iRSSIcount == 1)
  964.       atomic usRSSIVal = data;
  965.     else if (data > usRSSIVal)
  966.       atomic usRSSIVal = data;
  967.     if (iRSSIcount == CC1K_MaxRSSISamples) {
  968.       atomic {
  969.         bRSSIValid = TRUE;
  970.         sMacDelay = (call Random.rand() & 0xF) + 1;
  971.         RadioState = IDLE_STATE;
  972.       }
  973.     }
  974.     else
  975.       call RSSIADC.getData();
  976.     break;
  977.   case IDLE_STATE:
  978.     atomic usTempSquelch = data;
  979.     post adjustSquelch();
  980.     break;
  981.   case RX_STATE:
  982.   case HEADER_RX_STATE:
  983.   case RX_STATE_TINYSEC:
  984.     atomic usRSSIVal = data;
  985.     break;
  986.  
  987.   default:
  988.   }
  989.   return SUCCESS;
  990. }
  991.  // XXX:JP- for testing the mac layer squlech value
  992.  command uint16_t GetSquelch() {
  993.    return usSquelchVal;
  994.  }
  995. // Default events for radio send/receive coordinators do nothing.
  996. // Be very careful using these, you'll break the stack.
  997. default async event void RadioSendCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset, TOS_MsgPtr msgBuff) { }
  998. default async event void RadioSendCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  999. default async event void RadioSendCoordinator.blockTimer() { }
  1000. default async event void RadioReceiveCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset, TOS_MsgPtr msgBuff) { }
  1001. default async event void RadioReceiveCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
  1002. default async event void RadioReceiveCoordinator.blockTimer() { }
  1003. }