📄 cc1000radiointtinysecm.nc
字号:
// $Id: CC1000RadioIntTinySecM.nc,v 1.5.2.6 2003/08/26 09:08:16 cssharp Exp $/* tab:4 * "Copyright (c) 2000-2003 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Copyright (c) 2002-2003 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, * 94704. Attention: Intel License Inquiry. *//* * Authors: Philip Buonadonna, Jaein Jeong, Joe Polastre, Chris Karlof * Date last modified: $Revision: 1.5.2.6 $ * * This module provides the layer2 functionality for the mica2 radio. * While the internal architecture of this module is not CC1000 specific, * It does make some CC1000 specific calls via CC1000Control. * * * This makes use of TinySec. WARNING: Beware of using RadioCoordinators * with this stack. Length and group byte are switched. * * $Id: CC1000RadioIntTinySecM.nc,v 1.5.2.6 2003/08/26 09:08:16 cssharp Exp $ *//** * @author Philip Buonadonna * @author Jaein Jeong * @author Joe Polastre * @author Chris Karlof */includes crc;module CC1000RadioIntTinySecM { provides { interface StdControl; interface BareSendMsg as Send; interface ReceiveMsg as Receive; command result_t EnableRSSI(); command result_t DisableRSSI(); command result_t SetListeningMode(uint8_t power); command uint8_t GetListeningMode(); command result_t SetTransmitMode(uint8_t power); command uint8_t GetTransmitMode(); interface RadioCoordinator as RadioSendCoordinator; interface RadioCoordinator as RadioReceiveCoordinator; interface TinySecRadio; } uses { interface PowerManagement; interface StdControl as CC1000StdControl; interface CC1000Control; interface Random; interface ADCControl; interface ADC as RSSIADC; interface SpiByteFifo; interface StdControl as TimerControl; interface Timer as WakeupTimer; // TinySec interface TinySec; interface Leds; }}implementation { enum { TX_STATE, DISABLED_STATE, IDLE_STATE, PRETX_STATE, SYNC_STATE, HEADER_RX_STATE, RX_STATE, RX_STATE_TINYSEC, POWER_DOWN_STATE, }; enum { TXSTATE_WAIT, TXSTATE_START, TXSTATE_PREAMBLE, TXSTATE_SYNC, TXSTATE_DATA, TXSTATE_DATA_TINYSEC, TXSTATE_CRC, TXSTATE_FLUSH, TXSTATE_DONE }; enum { SYNC_BYTE = 0x33, NSYNC_BYTE = 0xcc, SYNC_WORD = 0x33cc, NSYNC_WORD = 0xcc33 }; uint8_t RadioState; uint8_t RadioTxState; uint16_t txlength; uint16_t rxlength; /**** TinySec ****/ TOS_Msg_TinySecCompat* txbufptr; // pointer to transmit buffer TOS_Msg_TinySecCompat* rxbufptr; // pointer to receive buffer TOS_Msg_TinySecCompat RxBuf; // save received messages /**** TinySec ****/ uint8_t NextTxByte; uint8_t lplpower; // low power listening mode uint8_t lplpowertx; // low power listening transmit mode uint16_t preamblelen; // current length of the preamble uint16_t PreambleCount; // found a valid preamble uint8_t SOFCount; union { uint16_t W; struct { uint8_t LSB; uint8_t MSB; }; } RxShiftBuf; uint8_t RxBitOffset; // bit offset for spibus uint16_t RxByteCnt; // received byte counter uint16_t TxByteCnt; uint16_t RSSISampleFreq; // in Bytes rcvd per sample bool bInvertRxData; // data inverted bool bTxPending; bool bTxBusy; bool bRSSIValid; uint16_t usRunningCRC; // Running CRC variable uint16_t usRSSIVal; uint16_t usSquelchVal; int16_t sMacDelay; // MAC delay for the next transmission // XXX-PB: // Here's the deal, the mica (RFM) radio stacks used TOS_LOCAL_ADDRESS // to determine if an L2 ack was reqd. This stack doesn't do L2 acks // and, thus doesn't need it. HOWEVER, some set-mote-id versions // break if this symbol is missing from the binary. // Thus, I put this LocalAddr here and set it to TOS_LOCAL_ADDRESS // to keep things happy for now. volatile uint16_t LocalAddr; ///********************************************************** //* local function definitions //**********************************************************/ /**** TinySec ****/ void swapLengthAndGroup(TOS_Msg* buf) { uint8_t tmp = buf->group; ((TOS_Msg_TinySecCompat*) buf)->length = buf->length; ((TOS_Msg_TinySecCompat*) buf)->group = tmp; } /**** TinySec ****/ task void PacketRcvd() { TOS_MsgPtr pBuf; atomic { rxbufptr->time = 0; /**** TinySec ****/ pBuf = (TOS_MsgPtr) rxbufptr; swapLengthAndGroup(pBuf); /**** TinySec ****/ // EWMA to determin squelch values usSquelchVal = (((5*pBuf->strength) + (3*usSquelchVal)) >> 3); } pBuf = signal Receive.receive((TOS_MsgPtr)pBuf); atomic { if (pBuf) rxbufptr = (TOS_Msg_TinySecCompat*) pBuf; rxbufptr->length = 0; //RadioState = IDLE_STATE; } call SpiByteFifo.enableIntr(); } task void PacketSent() { TOS_MsgPtr pBuf; //store buf on stack atomic { txbufptr->time = 0; pBuf = (TOS_Msg*) txbufptr; /**** TinySec ****/ swapLengthAndGroup(pBuf); /**** TinySec ****/ } signal Send.sendDone((TOS_MsgPtr)pBuf,SUCCESS); atomic bTxBusy = FALSE; } ///********************************************************** //* Exported interface functions //**********************************************************/ command result_t StdControl.init() { bool temp; atomic { RadioState = DISABLED_STATE; RadioTxState = TXSTATE_PREAMBLE; rxbufptr = &RxBuf; rxbufptr->length = 0; rxlength = TINYSEC_MSG_DATA_SIZE-TINYSEC_MAC_LENGTH; RxBitOffset = 0; PreambleCount = 0; RSSISampleFreq = 0; RxShiftBuf.W = 0; bTxPending = FALSE; bTxBusy = FALSE; bRSSIValid = FALSE; sMacDelay = -1; usRSSIVal = -1; lplpower = lplpowertx = 0; usSquelchVal = PRG_RDB(&CC1K_LPL_SquelchInit[lplpower]); } call SpiByteFifo.initSlave(); // set spi bus to slave mode call CC1000StdControl.init(); call CC1000Control.SelectLock(0x9); // Select MANCHESTER VIOLATION temp = call CC1000Control.GetLOStatus(); //Do we need to invert Rcvd Data? atomic bInvertRxData = temp; call ADCControl.bindPort(TOS_ADC_CC_RSSI_PORT,TOSH_ACTUAL_CC_RSSI_PORT); call ADCControl.init(); call Random.init(); call TimerControl.init(); // don't enable SPI interrupts until the radio is running //call SpiByteFifo.enableIntr(); // enable spi and spi interrupt LocalAddr = TOS_LOCAL_ADDRESS; return SUCCESS; } command result_t EnableRSSI() { return SUCCESS; } command result_t DisableRSSI() { return SUCCESS; } command uint8_t GetTransmitMode() { return lplpowertx; } /** * Set the state of low power transmit on the chipcon radio. * The transmit mode of the sender *must* match the receiver in * order for the receiver to successfully get the packet. * <p> * The default power up state is 0 (radio always on). * See CC1000Const.h for low power duty cycles and bandwidth */ command result_t SetTransmitMode(uint8_t power) { if ((power >= CC1K_LPL_STATES) || (power == lplpowertx)) return FAIL; // check if the radio is currently doing something if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || (RadioState == IDLE_STATE) || (RadioState == DISABLED_STATE))) { atomic { lplpowertx = power; preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) | PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1])); } return SUCCESS; } return FAIL; } /** * Set the state of low power listening on the chipcon radio. * <p> * The default power up state is 0 (radio always on). * See CC1000Const.h for low power duty cycles and bandwidth */ command result_t SetListeningMode(uint8_t power) { uint8_t oldRadioState; // valid low power listening values are 0 to 3 // 0 is "always on" and 3 is lowest duty cycle // 1 and 2 are in the middle if ((power >= CC1K_LPL_STATES) || (power == lplpower)) return FAIL; // check if the radio is currently doing something if ((!bTxPending) && ((RadioState == POWER_DOWN_STATE) || (RadioState == IDLE_STATE) || (RadioState == DISABLED_STATE))) { // change receiving function in CC1000Radio call WakeupTimer.stop(); atomic { if (lplpower == lplpowertx) { lplpowertx = power; } lplpower = power; oldRadioState = RadioState; if ((RadioState == IDLE_STATE) || (RadioState == POWER_DOWN_STATE)) { RadioState = DISABLED_STATE; } } // if successful, change power here if (oldRadioState == IDLE_STATE) { //RadioState = DISABLED_STATE; call StdControl.stop(); call StdControl.start(); } if (oldRadioState == POWER_DOWN_STATE) { //RadioState = DISABLED_STATE; call StdControl.start(); call PowerManagement.adjustPower(); } } else { return FAIL; } return SUCCESS; } /** * Gets the state of low power listening on the chipcon radio. * <p> * @return Current low power listening state value */ command uint8_t GetListeningMode() { return lplpower; } event result_t WakeupTimer.fired() { uint8_t oldRadioState; uint16_t sleeptime; bool bStayAwake; if (lplpower == 0) return SUCCESS; atomic { oldRadioState = RadioState; bStayAwake = bTxPending; } switch(oldRadioState) { case IDLE_STATE: sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) | PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1])); if (!bStayAwake) { atomic RadioState = POWER_DOWN_STATE; call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime); call CC1000StdControl.stop(); call SpiByteFifo.disableIntr(); } else { call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2); } break; case POWER_DOWN_STATE: sleeptime = PRG_RDB(&CC1K_LPL_SleepPreamble[lplpower]); atomic RadioState = IDLE_STATE; call CC1000StdControl.start(); call CC1000Control.BIASOn(); call SpiByteFifo.rxMode(); // SPI to miso call CC1000Control.RxMode(); call SpiByteFifo.enableIntr(); // enable spi interrupt call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime); break; default: call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2); } return SUCCESS; } command result_t StdControl.stop() { atomic RadioState = DISABLED_STATE; call WakeupTimer.stop(); call CC1000StdControl.stop(); call SpiByteFifo.disableIntr(); // disable spi interrupt return SUCCESS; } command result_t StdControl.start() { uint8_t chkRadioState; atomic chkRadioState = RadioState; if (chkRadioState == DISABLED_STATE) { atomic { rxbufptr->length = 0; RadioState = IDLE_STATE; bTxPending = bTxBusy = FALSE; sMacDelay = -1; preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) | PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1])); } if (lplpower == 0) { // all power on, captain! call CC1000StdControl.start(); call CC1000Control.BIASOn(); call SpiByteFifo.rxMode(); // SPI to miso call CC1000Control.RxMode(); call SpiByteFifo.enableIntr(); // enable spi interrupt } else { uint16_t sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) | PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1])); atomic RadioState = POWER_DOWN_STATE; call TimerControl.start(); call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime); } } return SUCCESS; } /*** TinySec ****/ async event result_t TinySec.sendDone(result_t result) { atomic { TxByteCnt = 0; RadioTxState = TXSTATE_FLUSH; } return result; } async event result_t TinySec.receiveInitDone(result_t result, uint16_t length, bool ts_enabled) { atomic { rxlength = length; if(result == SUCCESS) { if(ts_enabled) RadioState = RX_STATE_TINYSEC; else RadioState = RX_STATE; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -