CC1000RadioIntM-HCLOpt.nc
上传用户:joranyuan
上传日期:2022-06-23
资源大小:3306k
文件大小:55k
- includes crc;
- includes CC1000Const;
- includes zmacInfo;
- includes DrandInfo;
- module CC1000RadioIntM {
- provides {
- interface StdControl;
- interface BareSendMsg as Send;
- interface ReceiveMsg as Receive;
- interface RadioCoordinator as RadioSendCoordinator;
- interface RadioCoordinator as RadioReceiveCoordinator;
- interface MacControl;
- interface MacBackoff;
- interface LowPowerListening;
- interface SetDrand;
-
- // legacy commands supported, but should now use the
- // Low Power Listening interface
- async command result_t SetListeningMode(uint8_t power);
- async command uint8_t GetListeningMode();
- async command result_t SetTransmitMode(uint8_t power);
- async command uint8_t GetTransmitMode();
- // Used for debugging the noise floor (gets the current squelch value)
- async command uint16_t GetSquelch();
- // Used for debugging; gets an estimate of the power consumed by the radio
- async command uint16_t GetPower();
- async command uint16_t GetDataSent();
- async command uint16_t GetPower_tx();
- async command uint16_t GetPower_rx();
- async command uint16_t GetPower_sp();
- async command result_t ResetPower();
- async command result_t ResetDataSent();
- }
- uses {
- interface SClock;
- interface StdControl as SubControl;
- 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;
- interface Timer as SquelchTimer;
- interface Timer as TDMATimer;
- interface Leds;
- }
- }
- implementation {
- #include "DrandMSG.h"
- #include "zmacConst.h"
- #ifdef ZMAC_DEBUG
- #include "SODebug.h"
- #endif
- enum {
- NULL_STATE,
- TX_STATE,
- DISABLED_STATE,
- IDLE_STATE,
- PRETX_STATE,
- SYNC_STATE,
- RX_STATE,
- SENDING_ACK,
- POWER_DOWN_STATE,
- PULSE_CHECK_STATE,
- };
- enum {
- TXSTATE_WAIT,
- TXSTATE_START,
- TXSTATE_PREAMBLE,
- TXSTATE_SYNC,
- TXSTATE_DATA,
- TXSTATE_CRC,
- TXSTATE_FLUSH,
- TXSTATE_WAIT_FOR_ACK,
- TXSTATE_READ_ACK,
- TXSTATE_DONE
- };
- enum {
- SYNC_BYTE = 0x33,
- NSYNC_BYTE = 0xcc,
- SYNC_WORD = 0x33cc,
- NSYNC_WORD = 0xcc33,
- ACK_LENGTH = 16,
- MAX_ACK_WAIT = 18,
- TIME_BETWEEN_CHECKS = 50,
- TIME_AFTER_CHECK = 30,
- CHECK_MA_COUNT = 100, //8888,
- SEND_MA_COUNT = 100, //7200,
- PREAMBLE_LENGTH_TO_BASE = 8,
- RECEIVE_MA_COUNT = 100, //9600
- };
- uint8_t ack_code[5] = {0xab, 0xba, 0x83, 0xaa, 0xaa};
- uint8_t RadioState;
- uint8_t RadioTxState;
- norace uint8_t iRSSIcount;
- uint8_t RSSIInitState;
- uint8_t iSquelchCount;
- uint16_t txlength;
- uint16_t rxlength;
- TOS_MsgPtr txbufptr; // pointer to transmit buffer
- TOS_MsgPtr rxbufptr; // pointer to receive buffer
- TOS_Msg retxbuf; //re-transmit buffer in case ECN preempts send
- TOS_Msg RxBuf; // save received messages
- 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 sleeptime; // current check interval (sleep time)
-
- uint16_t PreambleCount; // found a valid preamble
- uint8_t SOFCount;
- uint16_t search_word;
- //modified by Mahesh
- enum {
- BMAC,
- ZMAC
- };
- enum{
- MAX_VAL = 0xFFFF
- };
- enum{
- POSITIVE = 1,
- NEGATIVE = 2,
- ZERO = 3
- };
-
- // nodeInfo *nbrInfo;
- nodeInfo nbrInfo[MAX_NBR], myInfo; //CHANGE THIS, ONLY FOR TESTING !!!!!!!
- GTime currentDiff, constOffset;
- uint16_t currentSender;
- uint8_t currentSign;
- uint8_t currentMAC; // default must be BMAC and change to ZMAC after DRAND completes
- uint16_t localFrameLength; // local frame length in slots
- uint16_t globalFrameLength;
- uint16_t slotSize;
- uint16_t nextHop;
- uint16_t ownSlot;
- uint16_t slots_since_ecnsend;
- uint16_t slots_since_ecnrecv;
- uint16_t slots_since_ecncheck;
- uint16_t globalFrameSize;
- uint16_t localFrameSize;
- uint16_t globalSlot;
- uint16_t currentSlot;
- uint16_t slotMultiplier;
- uint32_t slotNum;
- uint16_t packetsSent;
- uint16_t pktsLastSync;
- bool needTimeSync;
- uint16_t congBackOffs;
- double avgLoss;
- uint32_t curHCLlist;
- bool HCLselect;
- bool ackOrig;
- bool ecnPending;
- bool ecnforward;
- bool enableHCL;
- bool pureHCL;
- TOS_Msg ecnMsgHdr;
- TOS_Msg ecnForwardMsgHdr;
- TOS_Msg syncMsgHdr;
- 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
- norace bool bInvertRxData; // data inverted
- norace bool bTxPending;
- bool bAckEnable;
- bool bCCAEnable;
- bool bTxBusy;
- bool bRSSIValid;
- uint16_t CC1K_PulseLevel;
- uint16_t usRunningCRC; // Running CRC variable
- uint16_t usRSSIVal;
- uint16_t usSquelchVal;
- uint16_t usTempSquelch;
- uint8_t usSquelchIndex;
- norace uint8_t pulse_check_count;
- norace uint16_t pulse_check_sum;
- norace uint16_t send_sum;
- norace uint16_t receive_sum;
- norace uint16_t power_sum;
- norace uint16_t sp_sum;
- norace uint16_t rx_sum;
- norace uint16_t tx_sum;
- norace uint16_t dataSent;
- uint16_t usSquelchTable[CC1K_SquelchTableSize];
- 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
- //**********************************************************/
- /*
- int sortByShort(const void *x, const void *y) {
- uint16_t* x1 = (uint16_t*)x;
- uint16_t* y1 = (uint16_t*)y;
- if (x1[0] > y1[0]) return -1;
- if (x1[0] == y1[0]) return 0;
- if (x1[0] < y1[0]) return 1;
- return 0; // shouldn't reach here becasue it covers all the cases
- }
- */
- uint16_t getOwnerBackoff(){
- return (call Random.rand() & (T_O - 1)) + 1;
- }
- uint16_t getNonOwnerBackoff(){
- return (call Random.rand() & (T_NO - 1)) + T_O + 1;
- }
- void DivTime2(GTime* B, GTime* A){
- if (A->mticks % 2 == 1){
- B->mticks = (A->mticks >> 1);
- B->sticks = (A->sticks >> 1) + ((MAX_VAL) >>1);
- }
- else{
- B->mticks = (A->mticks >>1);
- B->sticks = (A->sticks >>1);
- }
- }
- void AddTime(GTime* C, GTime* A, GTime* B){
- if ((MAX_VAL - B->sticks) < A->sticks){
- C->sticks = A->sticks - (MAX_VAL - B->sticks);
- C->mticks = A->mticks + B->mticks + 1;
- }
- else{
- C->sticks = A->sticks + B->sticks;
- C->mticks = A->mticks + B->mticks;
- }
- }
- void SubTime(GTime* C, GTime* A, GTime* B){
- if (B->sticks > A->sticks){
- C->sticks = MAX_VAL - (B->sticks - A->sticks);
- C->mticks = A->mticks - (B->mticks + 1);
- }
- else {
- C->sticks = A->sticks - B->sticks;
- C->mticks = A->mticks - B->mticks;
- }
- }
- uint16_t getZMACBackoff(uint16_t residualBackoff){
- if(residualBackoff > 0){
- congBackOffs++;
- if((currentSlot == ownSlot) && (residualBackoff >= T_O)){
- return getOwnerBackoff();
- } else if((currentSlot != ownSlot) && (residualBackoff < T_O)){
- if((residualBackoff + T_O) < (T_O + T_NO))
- return (residualBackoff + T_O);
- else
- return getNonOwnerBackoff();
- } else
- return residualBackoff;
- } else{
- if(currentSlot == ownSlot)
- return getOwnerBackoff();
- else
- return getNonOwnerBackoff();
- }
- }
- uint8_t ModSubTime(GTime* C, GTime* A, GTime* B){
- uint8_t retval;
- if (A->mticks > B->mticks)
- retval = POSITIVE;
- else if (A->mticks < B->mticks)
- retval = NEGATIVE;
- else{
- if (A->sticks > B->sticks)
- retval = POSITIVE;
- else if (A->sticks < B->sticks)
- retval = NEGATIVE;
- else
- retval = ZERO;
- }
- if (retval == POSITIVE) SubTime(C,A,B);
- else if (retval == NEGATIVE) SubTime(C,B,A);
- else {
- C->sticks = 0;
- C->mticks = 0;
- }
- return retval;
- }
- bool IsHCL(uint32_t gSlot){
- uint32_t tempHCL = 0x1;
- bool flag;
- tempHCL = tempHCL << gSlot;
- atomic{
- if(tempHCL & curHCLlist)
- flag = TRUE;
- else
- flag = FALSE;
- }
- return flag;
- }
- task void adjustSquelch() {
- uint16_t tempArray[CC1K_SquelchTableSize];
- char i,j,min;
- uint16_t min_value;
- uint32_t tempsquelch;
- atomic {
- usSquelchTable[usSquelchIndex] = usTempSquelch;
- usSquelchIndex++;
- if (usSquelchIndex >= CC1K_SquelchTableSize)
- usSquelchIndex = 0;
- if (iSquelchCount <= CC1K_SquelchCount)
- iSquelchCount++;
- }
- for (i=0; i<CC1K_SquelchTableSize; i++) {
- tempArray[(int)i] = usSquelchTable[(int)i];
- }
- min = 0;
- // for (j = 0; j < ((CC1K_SquelchTableSize) >> 1); j++) {
- for (j = 0; j < 3; j++) {
- for (i = 1; i < CC1K_SquelchTableSize; i++) {
- if ((tempArray[(int)i] != 0xFFFF) &&
- ((tempArray[(int)i] > tempArray[(int)min]) ||
- (tempArray[(int)min] == 0xFFFF))) {
- min = i;
- }
- }
- min_value = tempArray[(int)min];
- tempArray[(int)min] = 0xFFFF;
- }
- tempsquelch = ((uint32_t)(usSquelchVal << 5) + (uint32_t)(min_value << 1));
- atomic usSquelchVal = (uint16_t)((tempsquelch / 34) & 0x0FFFF);
- /*
- // XXX: qsort actually causes ~600bits/sec lower bandwidth... why???
- //
- qsort (tempArray,CC1K_SquelchTableSize, sizeof(uint16_t),sortByShort);
- min_value = tempArray[CC1K_SquelchTableSize >> 1];
- atomic usSquelchVal = ((usSquelchVal << 5) + (min_value << 1)) / 34;
- */
- }
- void getTimeDiff(){ // called as soon as time sync message is received, regardless of crc
- atomic{
- uint16_t i, trust;
- GTime loctime, timeStamp;
- syncMsgType* syncMsgPtr = (syncMsgType *) rxbufptr->data;
- timeStamp.mticks = syncMsgPtr->mticks;
- timeStamp.sticks = syncMsgPtr->sticks;
- trust = syncMsgPtr->trust;
- currentSender = syncMsgPtr->sender;
- call SClock.getTime(&loctime);
- currentSign = ModSubTime(¤tDiff, &timeStamp, &loctime);
- if(trust < MIN_TRUST)
- trust = MIN_TRUST;
- if(trust < MAX_TRUST){
- for(i = 0; i < trust; i++){
- DivTime2(¤tDiff, ¤tDiff);
- }
- }
- }
- }
- void Blacklist(uint8_t slot, uint8_t fsize){
- uint8_t black_slot;
- atomic {
- if(fsize <= globalFrameLength){
- black_slot = slot;
- while(black_slot < globalFrameLength){
- uint32_t tempHCL2 = 0x1;
- tempHCL2 = tempHCL2 << black_slot;
- curHCLlist = curHCLlist | tempHCL2;
- black_slot = black_slot + fsize;
- }
- }
- }
- }
-
- task void adjustTime(){
- needTimeSync = TRUE;
- call SClock.setTime(currentSign, ¤tDiff);
- #ifdef ZMAC_TIME_SYNC
- SODbg(DBG_USR2, "diff = %u, %u, from %un", currentDiff.mticks, currentDiff.sticks, currentSender);
- #endif
- }
- task void PacketRcvd(){
- TOS_MsgPtr pBuf;
- ecnForwardMsgType *recvEcnMsgPtr;
- ecnForwardMsgType *ecnForwardMsgPtr;
- atomic {
- if(pktsLastSync > SYNC_PERIOD){
- atomic{
- ackOrig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&syncMsgHdr);
- pktsLastSync = 0;
- }
- pktsLastSync++;
- rxbufptr->time = 0;
- pBuf = rxbufptr;
- recvEcnMsgPtr = (ecnForwardMsgType *) rxbufptr->data;
- ecnForwardMsgPtr = (ecnForwardMsgType *) ecnForwardMsgHdr.data;
- #ifdef ZMAC_ECN
- if((currentMAC == ZMAC) && (pBuf->type == ECNTYPE)){
- SODbg(DBG_USR2,"Received %u hop ECN from %u, deciding whether significant..n",
- recvEcnMsgPtr->hopCount, recvEcnMsgPtr->senderAddress);
- }
- #endif
- if((currentMAC == ZMAC) && (HCLselect) && (pBuf->type == ECNTYPE) && (pBuf->crc != 0) &&
- (recvEcnMsgPtr->senderAddress != TOS_LOCAL_ADDRESS)){ //Message is an ECN
- if((recvEcnMsgPtr->hopCount == 0) && (recvEcnMsgPtr->nextHop == TOS_LOCAL_ADDRESS)){
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"Received one-hop ECN from %un", recvEcnMsgPtr->senderAddress);
- #endif
- ecnForwardMsgPtr->hopCount = 1;
- ecnForwardMsgPtr->nextHop = nextHop;
- ecnForwardMsgPtr->senderAddress = TOS_LOCAL_ADDRESS;
- if(!bTxBusy){
- ackOrig = bAckEnable;
- bAckEnable = FALSE;
- call Send.send(&ecnForwardMsgHdr); //take care of case where we are not currently sending
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"Forwarded ECNn");
- #endif
- } else
- ecnforward = TRUE;
- } else if(recvEcnMsgPtr->hopCount == 1){ //check if two-hop ECN
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"????????????????????? Received two hop ECN from %un", recvEcnMsgPtr->senderAddress);
- #endif
- atomic enableHCL = TRUE;
- SODbg(DBG_USR2,"Going into ECNn");
- if(recvEcnMsgPtr->senderAddress == nextHop){ //check forwarding node's address
- //suppress ECN
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"Suppressed own ECNn");
- #endif
- atomic ecnPending = FALSE;
- slots_since_ecnsend = 0;
- slots_since_ecnrecv = 0;
- }
- }
- } else if((pBuf->type != SYNCTYPE) && (pBuf->type != ECNTYPE)){
- #ifdef ZMAC_ECN
- // SODbg(DBG_USR2,"Received packet of type %u, crc = %un", pBuf->type, pBuf->crc);
- #endif
- pBuf = signal Receive.receive((TOS_MsgPtr)pBuf);
- }
-
- if (pBuf)
- rxbufptr = pBuf;
- rxbufptr->length = 0;
- }
- call SpiByteFifo.enableIntr();
- }
-
- task void PacketSent() {
- TOS_MsgPtr pBuf; //store buf on stack
- atomic {
- txbufptr->time = 0;
- pBuf = txbufptr;
- }
-
- if ((txbufptr->type != ECNTYPE) && (txbufptr->type != SYNCTYPE)){
- if(txbufptr->type == AM_MULTIHOP)
- dataSent++;
- signal Send.sendDone((TOS_MsgPtr)pBuf, SUCCESS);
- } else if(txbufptr->type == SYNCTYPE){
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2, "Sent one sync message $$$$$$$$$n");
- #endif
- } else if(txbufptr->type == ECNTYPE){
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2, "Sent one ecn message $$$$$$$$$n");
- #endif
- }
-
- atomic bTxBusy = FALSE;
- if(pktsLastSync > SYNC_PERIOD){
- atomic{
- ackOrig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&syncMsgHdr);
- pktsLastSync = 0;
- } else if((currentMAC == ZMAC) && (ecnforward == TRUE)){
- atomic{
- ackOrig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&ecnForwardMsgHdr);
- atomic ecnforward = FALSE;
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"Forwarded ECNn");
- #endif
- } else if((currentMAC == ZMAC) && (ecnPending == TRUE)){
- atomic{
- ackOrig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&ecnMsgHdr);
- atomic ecnPending = FALSE;
- atomic slots_since_ecnsend = 0;
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"Sent own ECNn");
- #endif
- }
- }
- ///**********************************************************
- //* Exported interface functions
- //**********************************************************/
- command void SetDrand.setParent(uint8_t id){ nextHop = id; }
- command result_t SetDrand.Set(nodeInfo *mInfo, uint8_t nHop, nodeInfo *nInfo, uint16_t sSize){
- uint32_t slotOffset = 0, globalTimeStamp = 0;
- GTime loctime;
- uint8_t i = 0;
- slotSize = sSize;
- nextHop = nHop;
- if(0){
- /* localFrameLength = myInfo->frame; */
- /* ownSlot = myInfo->slot; */
- /* nbrInfo = nInfo; */
- /* for(i = 0; (i < MAX_NBR) && (nbrInfo[i].nodeID != 0xFF); i++) */
- /* if(nbrInfo[i].bitMap & TWO_HOP) */
- /* Blacklist(nbrInfo[i].slot, nbrInfo[i].frame); */
- } else{ // USE THIS ONLY FOR TESTING
- for(i = 0 ; i<MAX_NBR ; i++){ // initialize the nbr table
- nbrInfo[i].nodeID = 0xFF;
- nbrInfo[i].slot = 0xFF;
- nbrInfo[i].frame = 0xFF;
- nbrInfo[i].bitMap = 0x0;
- }
- #include "nbrTable.h"
- /* slotSize = sSize; */
- /* localFrameLength = 8; */
- /* nextHop = nHop; */
- /* switch(TOS_LOCAL_ADDRESS){ */
- /* case 1: */
- /* ownSlot = 6; */
- /* break; */
- /* case 10: */
- /* ownSlot = 4; */
- /* break; */
- /* case 11: */
- /* ownSlot = 0; */
- /* break; */
- /* case 13: */
- /* ownSlot = 1; */
- /* break; */
- /* case 2: */
- /* ownSlot = 1; */
- /* break; */
- /* case 20: */
- /* ownSlot = 1; */
- /* break; */
- /* case 21: */
- /* ownSlot = 2; */
- /* break; */
- /* case 22: */
- /* ownSlot = 7; */
- /* break; */
- /* case 24: */
- /* ownSlot = 0; */
- /* break; */
- /* case 0: */
- /* ownSlot = 5; */
- /* break; */
- /* case 8: */
- /* ownSlot = 2; */
- /* break; */
- /* case 9: */
- /* ownSlot = 3; */
- /* break; */
- /* } */
- }
- localFrameSize = localFrameLength * slotSize;
- globalFrameSize = globalFrameLength * slotSize;
- slotMultiplier = (uint16_t) (slotSize * 1.024);
- call SClock.getTime(&loctime);
- globalTimeStamp = (uint32_t)(loctime.mticks * 568.889 + loctime.sticks * 0.00868056); //in ms
- slotOffset = (uint32_t) (1.024 * (slotSize - (globalTimeStamp % slotSize))); // in timer units .976562 = 1000/1024
- slotNum = (uint32_t) (globalTimeStamp/slotSize);
- currentSlot = slotNum & (localFrameLength - 1);
- globalSlot = slotNum & (globalFrameLength - 1);
-
- call TDMATimer.start(TIMER_ONE_SHOT, slotOffset);
- #ifdef ZMAC_TIMER
- // SODbg(DBG_USR2,"Started timer slotsize - offset is %in",slotSize - slotOffset);
- #endif
- return SUCCESS;
- }
- command result_t StdControl.init() {
- char i;
- ecnMsgType *ecnMsgPtr = (ecnMsgType *) ecnMsgHdr.data;
- atomic {
- RadioState = DISABLED_STATE;
- RadioTxState = TXSTATE_PREAMBLE;
- rxbufptr = &RxBuf;
- rxbufptr->length = 0;
- rxlength = MSG_DATA_SIZE-2;
- RxBitOffset = 0;
- iSquelchCount = 0;
-
- PreambleCount = 0;
- RSSISampleFreq = 0;
- RxShiftBuf.W = 0;
- iRSSIcount = 0;
- bTxPending = FALSE;
- bTxBusy = FALSE;
- bRSSIValid = FALSE;
- bAckEnable = FALSE; // to test for ECN only
- bCCAEnable = TRUE;
- CC1K_PulseLevel = 300;
- sMacDelay = -1;
- usRSSIVal = -1;
- usSquelchIndex = 0;
- pulse_check_count = 0;
- lplpower = 0;//0x87;
- RSSIInitState = NULL_STATE;
- // if(TOS_LOCAL_ADDRESS == 0) lplpower = 0;
- // lplpowertx = 7;
- usSquelchVal = CC1K_SquelchInit;
- currentMAC = BMAC;
- congBackOffs = 0;
- packetsSent = 0;
- pktsLastSync = 0;
- avgLoss = 0.0;
- curHCLlist = 0;
- globalFrameLength = GLOBAL_FRAME_LENGTH;
- localFrameLength = GLOBAL_FRAME_LENGTH;
- slotSize = 50;
- localFrameSize = localFrameLength * slotSize;
- globalFrameSize = globalFrameLength * slotSize;
- ackOrig = bAckEnable;
- ecnPending = FALSE;
- ecnforward = FALSE;
- enableHCL = FALSE; // ecn flag, set if currently ecn is going on ...
- pureHCL = FALSE;
- HCLselect = SELECTHCL;
- needTimeSync = FALSE;
- slots_since_ecnsend = 0;
- slots_since_ecnrecv = 0;
- slots_since_ecncheck = 0;
- ecnMsgHdr.type = ECNTYPE; //set ecnMsg headers
- ecnMsgHdr.addr = TOS_BCAST_ADDR; //ECN Indicator;
- ecnMsgHdr.length = sizeof(ecnMsgType);
- ecnMsgHdr.group = 125;
- ecnMsgHdr.crc = 0;
- ecnForwardMsgHdr.type = ECNTYPE;
- ecnForwardMsgHdr.addr = TOS_BCAST_ADDR;
- ecnForwardMsgHdr.length = sizeof(ecnMsgType);
- ecnForwardMsgHdr.group = 125;
- ecnForwardMsgHdr.crc = 0;
- syncMsgHdr.type = SYNCTYPE; //set syncMsg headers
- syncMsgHdr.addr = TOS_BCAST_ADDR; //SYNC Indicator;
- syncMsgHdr.length = sizeof(syncMsgType);
- syncMsgHdr.group = 125;
- syncMsgHdr.crc = 0;
-
- ecnMsgPtr->hopCount = 0; //hopcount
- ecnMsgPtr->nextHop = nextHop; //parent node
- ecnMsgPtr->senderAddress = TOS_LOCAL_ADDRESS;
- }
- for (i = 0; i < CC1K_SquelchTableSize; i++)
- usSquelchTable[(int)i] = CC1K_SquelchInit;
- call SpiByteFifo.initSlave(); // set spi bus to slave mode
-
- call CC1000StdControl.init();
- call CC1000Control.SelectLock(0x9); // Select MANCHESTER VIOLATION
- bInvertRxData = call CC1000Control.GetLOStatus();
- call ADCControl.bindPort(TOS_ADC_CC_RSSI_PORT,TOSH_ACTUAL_CC_RSSI_PORT);
- call ADCControl.init();
-
- call Random.init();
- call TimerControl.init();
- #ifdef ZMAC_DEBUG
- init_debug();
- #endif
- LocalAddr = TOS_LOCAL_ADDRESS;
- return SUCCESS;
- }
-
- /**
- * Get the current Low Power Listening transmit mode
- * @return mode number (see SetListeningMode)
- */
- async command uint8_t LowPowerListening.GetTransmitMode() {
- return lplpowertx;
- }
- // legacy support
- async command uint8_t GetTransmitMode() {
- return call LowPowerListening.GetTransmitMode();
- }
- /**
- * Set the transmit mode. This allows for hybrid schemes where
- * the transmit mode is different than the receive mode.
- * Use SetListeningMode first, then change the mode with SetTransmitMode.
- *
- * @param mode mode number (see SetListeningMode)
- * @return SUCCESS if the mode was successfully changed
- */
- async command result_t LowPowerListening.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;
- }
- // legacy support
- async command result_t SetTransmitMode(uint8_t power) {
- return call LowPowerListening.SetTransmitMode(power);
- }
- /**
- * Set the current Low Power Listening mode.
- * Setting the LPL mode sets both the check interval and preamble length.
- *
- * Modes include:
- * 0 = Radio full on
- * 1 = 10ms check interval
- * 2 = 25ms check interval
- * 3 = 50ms check interval
- * 4 = 100ms check interval (recommended)
- * 5 = 200ms check interval
- * 6 = 400ms check interval
- * 7 = 800ms check interval
- * 8 = 1600ms check interval
- *
- * @param mode the mode number
- * @return SUCCESS if the mode was successfully changed
- */
- async command result_t LowPowerListening.SetListeningMode(uint8_t power) {
- // valid low power listening values are 0 to 8
- // 0 is "always on" and 8 is lowest duty cycle
- 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;
- }
- // if successful, change power here
- if (RadioState == IDLE_STATE) {
- RadioState = DISABLED_STATE;
- call StdControl.stop();
- call StdControl.start();
- }
- if (RadioState == POWER_DOWN_STATE) {
- RadioState = DISABLED_STATE;
- call StdControl.start();
- call PowerManagement.adjustPower();
- }
- }
- else {
- return FAIL;
- }
- return SUCCESS;
- }
- // legacy support
- async command result_t SetListeningMode(uint8_t power) {
- return call SetListeningMode(power);
- }
- /**
- * Gets the state of low power listening on the chipcon radio.
- * @return Current low power listening state value
- */
- async command uint8_t LowPowerListening.GetListeningMode() {
- return lplpower;
- }
- // legacy support
- async command uint8_t GetListeningMode() {
- return call LowPowerListening.GetListeningMode();
- }
- /**
- * Set the preamble length of outgoing packets
- *
- * @param bytes length of the preamble in bytes
- * @return SUCCESS if the preamble length was successfully changed
- */
- async command result_t LowPowerListening.SetPreambleLength(uint16_t bytes) {
- result_t result = FAIL;
- atomic {
- if (RadioState != TX_STATE) {
- preamblelen = bytes;
- result = SUCCESS;
- }
- }
- return result;
- }
- /**
- * Get the preamble length of outgoing packets
- *
- * @return length of the preamble in bytes
- */
- async command uint16_t LowPowerListening.GetPreambleLength() {
- return preamblelen;
- }
- /**
- * Set the check interval (time between waking up and sampling
- * the radio for activity in low power listening)
- *
- * @param ms check interval in milliseconds
- * @return SUCCESS if the check interval was successfully changed
- */
- async command result_t LowPowerListening.SetCheckInterval(uint16_t ms) {
- // sleep time will go into effect after the next wakeup time
- atomic sleeptime = ms;
- return SUCCESS;
- }
- /**
- * Get the check interval currently used by low power listening
- *
- * @return length of the check interval in milliseconds
- */
- async command uint16_t LowPowerListening.GetCheckInterval() {
- return sleeptime;
- }
- event result_t SquelchTimer.fired() {
- char currentRadioState;
- atomic currentRadioState = RadioState;
- if (currentRadioState == IDLE_STATE) {
- atomic RSSIInitState = currentRadioState;
- call RSSIADC.getData();
- }
- return SUCCESS;
- }
- event result_t WakeupTimer.fired() {
- uint8_t currentRadioState;
- if (lplpower == 0)
- return SUCCESS;
-
- atomic currentRadioState = RadioState;
- switch(currentRadioState) {
- case IDLE_STATE:
- if (!bTxPending || (enableHCL && IsHCL(currentSlot))) { // changed here for hcl optimization
- atomic {
- RadioState = POWER_DOWN_STATE;
- call SpiByteFifo.disableIntr();
- }
- call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
- call SquelchTimer.stop();
- call CC1000StdControl.stop();
- } else {
- call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
- }
- break;
- case POWER_DOWN_STATE:
- atomic RadioState = PULSE_CHECK_STATE;
- pulse_check_count = 0;
- call CC1000StdControl.start();
- call CC1000Control.BIASOn();
- call WakeupTimer.start(TIMER_ONE_SHOT, 1);
- return SUCCESS;
- break;
- case PULSE_CHECK_STATE:
- call CC1000Control.RxMode();
- if(!(call RSSIADC.getData())){
- call WakeupTimer.start(TIMER_ONE_SHOT, TIME_BETWEEN_CHECKS);
- atomic RadioState = POWER_DOWN_STATE;
- }
- else {
- TOSH_uwait(80);
- }
- call CC1000StdControl.stop();
- pulse_check_sum ++;
- break;
- default:
- call WakeupTimer.start(TIMER_ONE_SHOT, 5);
- }
- return SUCCESS;
- }
- task void IdleTimerTask(){
- if (iSquelchCount > CC1K_SquelchCount)
- call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
- else
- call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
- call WakeupTimer.start(TIMER_ONE_SHOT, TIME_AFTER_CHECK);
- /*if(pulse_check_sum > CHECK_MA_COUNT){
- power_sum ++;
- pulse_check_sum -= CHECK_MA_COUNT;
- }
- if(send_sum > SEND_MA_COUNT){
- power_sum ++;
- send_sum -= SEND_MA_COUNT;
- }
- if(receive_sum > RECEIVE_MA_COUNT){
- power_sum ++;
- receive_sum -= RECEIVE_MA_COUNT;
- }*/
- }
- //added by Mahesh
- event result_t TDMATimer.fired(){
- call TDMATimer.start(TIMER_ONE_SHOT, slotMultiplier);
- slotNum++;
- atomic currentMAC = ZMAC;
- atomic{
- currentSlot = slotNum & (localFrameLength - 1);
- globalSlot = slotNum & (globalFrameLength - 1);
- #ifdef ZMAC_TIMER
- SODbg(DBG_USR2,"*************Timer fired with current slot = %u, own slot = %un", currentSlot, ownSlot);
- #endif
- if(HCLselect){
- slots_since_ecnsend ++;
- slots_since_ecnrecv ++;
- slots_since_ecncheck++;
- if((packetsSent > ECNMINPACKETS) && (slots_since_ecncheck >= ECNCHECKPERIOD)){
- double currentLoss = (double)congBackOffs/packetsSent;
- avgLoss = ALPHA * (currentLoss) + (1 - ALPHA) * avgLoss;
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"#####################Congestion Statistics: %i / %i, %in", congBackOffs, packetsSent, (uint16_t) avgLoss);
- #endif
- slots_since_ecncheck = 0;
- congBackOffs = 0;
- packetsSent = 0;
- if((avgLoss > ECNTHRESHOLD) && (slots_since_ecnsend >= ECNSENDPERIOD)){
- ecnMsgType *ecnMsgPtr = (ecnMsgType *) ecnMsgHdr.data;
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"Setting ECN flagn");
- #endif
- // change by acw, go to ecn myself if sending ecn
- atomic enableHCL = TRUE;
- slots_since_ecnrecv = 0;
- // change by acw ends
- ecnMsgPtr->nextHop = nextHop;
- if(!pureHCL)
- ecnPending = TRUE;
- }
- }
- if((enableHCL) && (slots_since_ecnrecv >= ECNEXPIREPERIOD)){
- if(!pureHCL)
- enableHCL = FALSE;
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"ECN expired, into LCL againn");
- #endif
- }
-
- #ifdef ZMAC_ECN
- if(enableHCL)
- SODbg(DBG_USR2,"Current slot %i **********************n",currentSlot);
- #endif
- #ifdef ZMAC_ECN
- if(enableHCL && IsHCL(globalSlot) && ownSlot != currentSlot)
- SODbg(DBG_USR2,"***** ****** ****** ****** Current slot %i HCLn",currentSlot);
- #endif
- }
- // changed here for hcl optimization
- if((RadioState == POWER_DOWN_STATE) || (RadioState == DISABLED_STATE)){
- if (bTxPending && (!enableHCL || !IsHCL(currentSlot))) { // bug fixed by Dr. Rhee
- call CC1000Control.RxMode();
- RadioState = IDLE_STATE;
- call SpiByteFifo.rxMode(); // SPI to miso
- call SpiByteFifo.enableIntr(); // enable spi interrupt
- post IdleTimerTask();
- }
- }
- if(bTxPending){
- sMacDelay = getZMACBackoff(sMacDelay);
- #ifdef ZMAC_BACKOFF
- SODbg(DBG_USR2,"TDMATimerFired: backoff %un", sMacDelay);
- #endif
- }
- }
- return SUCCESS;
- }
-
- command result_t StdControl.stop() {
- atomic RadioState = DISABLED_STATE;
- call SquelchTimer.stop();
- call WakeupTimer.stop();
- call CC1000StdControl.stop();
- call SpiByteFifo.disableIntr(); // disable spi interrupt
- return SUCCESS;
- }
- command result_t StdControl.start() {
- uint8_t currentRadioState;
- atomic currentRadioState = RadioState;
- call SClock.SetRate(MAX_VAL,CLK_DIV_64);
- if (currentRadioState == DISABLED_STATE) {
- atomic {
- rxbufptr->length = 0;
- RadioState = IDLE_STATE;
- bTxPending = bTxBusy = FALSE;
- sMacDelay = -1;
- if(SLEEPTIME > 0){
- sleeptime = SLEEPTIME;
- preamblelen = PREAMBLELEN;
- } else{
- lplpower = lplpowertx = 0;
- sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) |
- PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1]));
- preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) |
- PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1]));
- }
- /* sleeptime = ((PRG_RDB(&CC1K_LPL_SleepTime[lplpower*2]) << 8) | */
- /* PRG_RDB(&CC1K_LPL_SleepTime[(lplpower*2)+1])); */
- /* preamblelen = ((PRG_RDB(&CC1K_LPL_PreambleLength[lplpowertx*2]) << 8) | */
- /* PRG_RDB(&CC1K_LPL_PreambleLength[(lplpowertx*2)+1])); */
- }
- // all power on, captain!
- rxbufptr->length = 0;
- atomic RadioState = IDLE_STATE;
- call CC1000StdControl.start();
- call CC1000Control.BIASOn();
- call SpiByteFifo.rxMode(); // SPI to miso
- call CC1000Control.RxMode();
- if (iSquelchCount > CC1K_SquelchCount)
- call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
- else
- call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
- call SpiByteFifo.enableIntr(); // enable spi interrupt
- if (lplpower > 0) {
- // set a time to start sleeping after measuring the noise floor
- call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_SquelchIntervalSlow);
- }
- }
- return SUCCESS;
- }
- command result_t Send.send(TOS_MsgPtr pMsg) {
- result_t Result = SUCCESS;
- uint8_t currentRadioState = 0;
-
- atomic {
- if (bTxBusy) {
- Result = FAIL;
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2, "Busy sending the message of type %u!n", txbufptr->type);
- #endif
- } else {
- bTxBusy = TRUE;
- txbufptr = pMsg;
- txlength = pMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
- if(bCCAEnable){ // initially back off [1,32] bytes (approx 2/3 packet)
- if(currentMAC == BMAC)
- sMacDelay = signal MacBackoff.initialBackoff(pMsg);
- else
- sMacDelay = getZMACBackoff(0);
- } else
- sMacDelay = 0;
- #ifdef ZMAC_BACKOFF
- SODbg(DBG_USR2, "SendMSG(): Need to send type %u, myslot %u, current slot %u backoff %un",
- txbufptr->type, ownSlot, currentSlot, sMacDelay);
- #endif
- bTxPending = TRUE;
- }
- currentRadioState = RadioState;
- }
- if (Result) {
- if (currentRadioState == POWER_DOWN_STATE){ //{ && (!enableHCL || !IsHCL(currentSlot))) { // if we're off, start the radio
- atomic RadioState = IDLE_STATE; // disable wakeup timer
- call WakeupTimer.stop();
- call CC1000StdControl.start();
- call CC1000Control.BIASOn();
- call CC1000Control.RxMode();
- call SpiByteFifo.rxMode(); // SPI to miso
- call SpiByteFifo.enableIntr(); // enable spi interrupt
- if (iSquelchCount > CC1K_SquelchCount)
- call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalSlow);
- else
- call SquelchTimer.start(TIMER_REPEAT, CC1K_SquelchIntervalFast);
- call WakeupTimer.start(TIMER_ONE_SHOT, CC1K_LPL_PACKET_TIME*2);
- }
- }
- return Result;
- }
-
- /**********************************************************
- * make a spibus interrupt handler
- * needs to handle interrupts for transmit delay
- * and then go into byte transmit mode with
- * timer1 baudrate delay as interrupt handler
- * else SODbg(DBG_USR2,"Sending Packet ..");
- * needs to handle interrupts for byte read and detect preamble
- * then handle reading a packet
- * PB - We can use this interrupt handler as a transmit scheduler
- * because the CC1000 continuously clocks in data, regarless
- * of whether it's good or not. Thus, this routine will be called
- * on every 8 ticks of DCLK.
- **********************************************************/
- async event result_t SpiByteFifo.dataReady(uint8_t data_in) {
- GTime loctime;
- signal RadioSendCoordinator.blockTimer();
- signal RadioReceiveCoordinator.blockTimer();
-
- if (bInvertRxData)
- data_in = ~data_in;
- #ifdef ENABLE_UART_DEBUG
- UARTPutChar(RadioState);
- #endif
- switch (RadioState) {
- case TX_STATE:
- {
- call SpiByteFifo.writeByte(NextTxByte);
- TxByteCnt++;
- switch (RadioTxState) {
-
- case TXSTATE_PREAMBLE:
- send_sum ++;
- if (!(TxByteCnt < preamblelen)||
- (txbufptr->strength == 0xffff && TxByteCnt >= PREAMBLE_LENGTH_TO_BASE)) {
- NextTxByte = SYNC_BYTE;
- RadioTxState = TXSTATE_SYNC;
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2,"Sent packet in slot %in",currentSlot);
- SODbg(DBG_USR2, "ishcl = %un", IsHCL(currentSlot));
- #endif
- }
- break;
- case TXSTATE_SYNC:
- send_sum ++;
- NextTxByte = NSYNC_BYTE;
- RadioTxState = TXSTATE_DATA;
- TxByteCnt = -1;
- if(txbufptr->type == SYNCTYPE){ // allow sync messages
- syncMsgType *syncMsgPtr = (syncMsgType *) txbufptr->data;
- call SClock.getTime(&loctime);
- syncMsgPtr->mticks = loctime.mticks;
- syncMsgPtr->sticks = loctime.sticks;
- syncMsgPtr->trust = TRUST_FACTOR;
- syncMsgPtr->sender = TOS_LOCAL_ADDRESS;
- }
- // for Time Sync services
- signal RadioSendCoordinator.startSymbol(8, 0, txbufptr);
- break;
- case TXSTATE_DATA:
- send_sum ++;
- if ((uint8_t)(TxByteCnt) < txlength){
- if((txbufptr->type == SYNCTYPE) && (TxByteCnt == 5)){ // 5 = offset of timestamp
- syncMsgType *syncMsgPtr = (syncMsgType *) txbufptr->data;
- call SClock.getTime(&loctime);
- AddTime(&loctime, &loctime, &constOffset);
- syncMsgPtr->mticks = loctime.mticks;
- syncMsgPtr->sticks = loctime.sticks;
- }
- NextTxByte = ((uint8_t *)txbufptr)[(TxByteCnt)];
- usRunningCRC = crcByte(usRunningCRC,NextTxByte);
- signal RadioSendCoordinator.byte(txbufptr, (uint8_t)TxByteCnt); // Time Sync
- }
- else {
- NextTxByte = (uint8_t)(usRunningCRC);
- RadioTxState = TXSTATE_CRC;
- }
- break;
- case TXSTATE_CRC:
- send_sum ++;
- NextTxByte = (uint8_t)(usRunningCRC>>8);
- RadioTxState = TXSTATE_FLUSH;
- TxByteCnt = 0;
- break;
- case TXSTATE_FLUSH:
- send_sum ++;
- if (TxByteCnt > 3) {
- TxByteCnt = 0;
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2,"Came heren");
- #endif
- if (bAckEnable)
- RadioTxState = TXSTATE_WAIT_FOR_ACK;
- else {
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2,"came inside: current MAC: %i ackenabled :%i,ecnPending: %i ecnforward %i ecnSENT %in",currentMAC,bAckEnable,ecnPending,ecnforward,sentECN);
- #endif
- packetsSent ++;
- call SpiByteFifo.rxMode();
- call CC1000Control.RxMode();
- RadioTxState = TXSTATE_DONE;
- }
- }
- break;
- case TXSTATE_WAIT_FOR_ACK:
- if(TxByteCnt == 1){
- send_sum ++;
- call SpiByteFifo.rxMode();
- call CC1000Control.RxMode();
- break;
- }
- receive_sum ++;
- if (TxByteCnt > 3) {
- RadioTxState = TXSTATE_READ_ACK;
- TxByteCnt = 0;
- search_word = 0;
- }
- break;
- case TXSTATE_READ_ACK:
- {
- uint8_t i;
- receive_sum ++;
- for(i = 0; i < 8; i ++){
- search_word <<= 1;
- if(data_in & 0x80) search_word |= 0x1;
- data_in <<= 1;
- if (search_word == 0xba83){
- txbufptr->ack = 1;
- RadioTxState = TXSTATE_DONE;
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2,"received ackn");
- #endif
- return SUCCESS;
- }
- }
- }
- if(TxByteCnt >= MAX_ACK_WAIT){
- txbufptr->ack = 0;
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2,"did not receive ack %i %i %in",lostacks,packetsSent,avgLoss * 100);
- #endif
- RadioTxState = TXSTATE_DONE;
- }
- break;
- case TXSTATE_DONE:
- default:
- bTxPending = FALSE;
- if((txbufptr->type == ECNTYPE) || (txbufptr->type == SYNCTYPE)){
- #ifdef ZMAC_ECN
- ecnForwardMsgType *ecnForwardMsgPtr = (ecnForwardMsgType *) txbufptr->data;
- if(txbufptr->type == ECNTYPE && ecnForwardMsgPtr->hopCount == 1)
- SODbg(DBG_USR2,"Successfully forwarded ECNn");
- #endif
- bAckEnable = ackOrig;
- }
- #ifdef ZMAC_BACKOFF
- SODbg(DBG_USR2, "Sent one packet of type %u, myslot %u, current slot %u!n", txbufptr->type,
- ownSlot, currentSlot);
- #endif
- if(post PacketSent()) {
- // If the post operation succeeds, goto Idle
- // otherwise, we'll try again.
- #ifdef ZMAC_DEBUG
- // SODbg(DBG_USR2,"Packet type %in",txbufptr->type);
- #endif
- RadioState = IDLE_STATE;
- pktsLastSync++;
- RSSIInitState = RadioState;
- call RSSIADC.getData();
- }
- break;
- }
- }
- break;
- case DISABLED_STATE:
- break;
- case IDLE_STATE:
- {
- receive_sum ++;
- if (((data_in == (0xaa)) || (data_in == (0x55)))) {
- PreambleCount++;
- if (PreambleCount > CC1K_ValidPrecursor) {
- PreambleCount = SOFCount = 0;
- RxBitOffset = RxByteCnt = 0;
- usRunningCRC = 0;
- rxlength = MSG_DATA_SIZE-2;
- RadioState = SYNC_STATE;
- }
- } else {
- if ((currentMAC == BMAC) || (enableHCL == FALSE) || (!IsHCL(currentSlot))) {
- if((bTxPending) && (--sMacDelay <= 0)){
- RadioState = PRETX_STATE;
- RSSIInitState = PRETX_STATE;
- bRSSIValid = FALSE;
- iRSSIcount = 0;
- PreambleCount = 0;
- call RSSIADC.getData();
- }
- } else{
- #ifdef ZMAC_ECN
- SODbg(DBG_USR2, "&&&&&&&&&&&&&&&&&&&&& ishcl = %un", IsHCL(currentSlot));
- #endif
- }
- }
- }
- break;
- case PRETX_STATE:
- {
- receive_sum ++;
- if (((data_in == (0xaa)) || (data_in == (0x55)))) {
- // Back to the penalty box.
- sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
- #ifdef ZMAC_BACKOFF
- SODbg(DBG_USR2,"SpiDataReady: detected preamble - backoff %un", sMacDelay);
- #endif
- RadioState = IDLE_STATE;
- }
- }
- break;
- case SYNC_STATE:
- {
- // draw in the preamble bytes and look for a sync byte
- // save the data in a short with last byte received as msbyte
- // and current byte received as the lsbyte.
- // use a bit shift compare to find the byte boundary for the sync byte
- // retain the shift value and use it to collect all of the packet data
- // check for data inversion, and restore proper polarity
- // XXX-PB: Don't do this.
- uint8_t i;
- receive_sum ++;
- if ((data_in == 0xaa) || (data_in == 0x55)) {
- // It is actually possible to have the LAST BIT of the incoming
- // data be part of the Sync Byte. SO, we need to store that
- // However, the next byte should definitely not have this pattern.
- // XXX-PB: Do we need to check for excessive preamble?
- RxShiftBuf.MSB = data_in;
- }
- else {
- // TODO: Modify to be tolerant of bad bits in the preamble...
- uint16_t usTmp;
- switch (SOFCount) {
- case 0:
- RxShiftBuf.LSB = data_in;
- break;
-
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- // bit shift the data in with previous sample to find sync
- usTmp = RxShiftBuf.W;
- RxShiftBuf.W <<= 8;
- RxShiftBuf.LSB = data_in;
- for(i=0;i<8;i++) {
- usTmp <<= 1;
- if(data_in & 0x80)
- usTmp |= 0x1;
- data_in <<= 1;
- // check for sync bytes
- if (usTmp == SYNC_WORD) {
- if (rxbufptr->length !=0) {
- call Leds.redToggle();
- RadioState = IDLE_STATE;
- }
- else {
- RadioState = RX_STATE;
- RSSIInitState = RX_STATE;
- call RSSIADC.getData();
- RxBitOffset = 7-i;
- // For time sync services
- signal RadioReceiveCoordinator.startSymbol(8, RxBitOffset, rxbufptr);
- }
- break;
- }
- }
- break;
- default:
- // We didn't find it after a reasonable number of tries, so....
- RadioState = IDLE_STATE; // Ensures we wait till the end of the transmission
- break;
- }
- SOFCount++;
- }
- }
- break;
- // collect the data and shift into double buffer
- // shift out data by correct offset
- // invert the data if necessary
- // stop after the correct packet length is read
- // return notification to upper levels
- // go back to idle state
- case RX_STATE:
- {
- char Byte;
- receive_sum ++;
- RxShiftBuf.W <<=8;
- RxShiftBuf.LSB = data_in;
- Byte = (RxShiftBuf.W >> RxBitOffset);
- ((char*)rxbufptr)[(int)RxByteCnt] = Byte;
- RxByteCnt++;
- signal RadioReceiveCoordinator.byte(rxbufptr, (uint8_t)RxByteCnt);
-
- if (RxByteCnt < rxlength) {
- usRunningCRC = crcByte(usRunningCRC,Byte);
- if (RxByteCnt == (offsetof(struct TOS_Msg,length) +
- sizeof(((struct TOS_Msg *)0)->length))) {
- rxlength = rxbufptr->length;
- if (rxlength > TOSH_DATA_LENGTH) {
- // The packet's screwed up, so just dump it
- rxbufptr->length = 0;
- RadioState = IDLE_STATE; // Waits till end of transmission
- return SUCCESS;
- }
- //Add in the header size
- rxlength += offsetof(struct TOS_Msg,data);
- }
- }
- else if (RxByteCnt == rxlength) {
- if(rxbufptr->type == SYNCTYPE) // got all bytes of time stamp !
- getTimeDiff();
- usRunningCRC = crcByte(usRunningCRC,Byte);
- // Shift index ahead to the crc field.
- RxByteCnt = offsetof(struct TOS_Msg,crc);
- }
- else if (RxByteCnt >= MSG_DATA_SIZE) {
- // Packet filtering based on bad CRC's is done at higher layers.
- // So sayeth the TOS weenies.
- if (rxbufptr->crc == usRunningCRC) {
- if(rxbufptr->type == SYNCTYPE)
- post adjustTime();
- rxbufptr->crc = 1;
-
- if(bAckEnable && (rxbufptr->addr == TOS_LOCAL_ADDRESS)){
- RadioState = SENDING_ACK;
- call CC1000Control.TxMode();
- call SpiByteFifo.txMode();
- call SpiByteFifo.writeByte(0xaa);
- RxByteCnt = 0;
- return SUCCESS;
- }
- } else {
- rxbufptr->crc = 0;
- }
- call SpiByteFifo.disableIntr();
-
- RadioState = IDLE_STATE; //DISABLED_STATE;
- if((currentMAC == ZMAC) && (bTxPending)){ //Ajit - reset timer when time slot boundary
- sMacDelay = getZMACBackoff(sMacDelay);
- #ifdef ZMAC_BACKOFF
- SODbg(DBG_USR2,"JustAfterReceive: backoff %u mySlot %u currentSlot %un", sMacDelay,
- ownSlot, currentSlot);
- #endif
- }
- rxbufptr->strength = usRSSIVal;
- if (!(post PacketRcvd())) {
- // If there are insufficient resources to process the incoming packet
- // we drop it
- rxbufptr->length = 0;
- RadioState = IDLE_STATE;
- call SpiByteFifo.enableIntr();
- }
- RSSIInitState = RadioState;
- call RSSIADC.getData();
- }
- }
- break;
- case SENDING_ACK:
- {
- send_sum ++;
- RxByteCnt++;
- if (RxByteCnt >= ACK_LENGTH) {
- call CC1000Control.RxMode();
- call SpiByteFifo.rxMode();
- call SpiByteFifo.disableIntr();
- RadioState = IDLE_STATE; //DISABLED_STATE;
- rxbufptr->strength = usRSSIVal;
- if (!(post PacketRcvd())) {
- rxbufptr->length = 0;
- RadioState = IDLE_STATE;
- call SpiByteFifo.enableIntr();
- }
- }else if(RxByteCnt >= ACK_LENGTH - sizeof(ack_code)){
- call SpiByteFifo.writeByte(ack_code[RxByteCnt + sizeof(ack_code) - ACK_LENGTH]);
- }
- }
- break;
- default:
- break;
- }
- if(pulse_check_sum > CHECK_MA_COUNT){
- power_sum ++;
- sp_sum++;
- pulse_check_sum -= CHECK_MA_COUNT;
- }
- if(send_sum > SEND_MA_COUNT){
- power_sum ++;
- tx_sum++;
- send_sum -= SEND_MA_COUNT;
- }
- if(receive_sum > RECEIVE_MA_COUNT){
- power_sum ++;
- rx_sum++;
- receive_sum -= RECEIVE_MA_COUNT;
- }
- return SUCCESS;
- }
- task void SleepTimerTask(){
- call WakeupTimer.start(TIMER_ONE_SHOT, sleeptime);
- }
- async event result_t RSSIADC.dataReady(uint16_t data) {
- atomic{
- uint8_t currentRadioState;
- // TOSH_CLR_PW3_PIN();
- currentRadioState = RadioState;
- // find the maximum RSSI value over CC1K_MAX_RSSI_SAMPLES
- switch(currentRadioState) {
- case IDLE_STATE:
- if (RSSIInitState == IDLE_STATE) {
- atomic usTempSquelch = data;
- post adjustSquelch();
- }
- RSSIInitState = NULL_STATE;
- break;
-
- case RX_STATE:
- if (RSSIInitState == RX_STATE) {
- atomic usRSSIVal = data;
- }
- RSSIInitState = NULL_STATE;
- break;
-
- case PRETX_STATE:
- iRSSIcount++;
-
- // if the channel is clear or CCA is disabled, GO GO GO!
- if (((data > (usSquelchVal + CC1K_SquelchBuffer)) ||
- (!bCCAEnable)) && (RSSIInitState == PRETX_STATE)) {
- call SpiByteFifo.writeByte(0xaa);
- call CC1000Control.TxMode();
- call SpiByteFifo.txMode();
-
- usRSSIVal = data;
- iRSSIcount = CC1K_MaxRSSISamples;
- bRSSIValid = TRUE;
- TxByteCnt = 0;
- usRunningCRC = 0;
- RadioState = TX_STATE;
- RadioTxState = TXSTATE_PREAMBLE;
- NextTxByte = 0xaa;
- RSSIInitState = NULL_STATE;
- }
- else {
- RSSIInitState = NULL_STATE;
- if (iRSSIcount == CC1K_MaxRSSISamples) {
- sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
- #ifdef ZMAC_BACKOFF
- SODbg(DBG_USR2,"adcDataReady: channel busy, backoff %un", sMacDelay);
- #endif
- RadioState = IDLE_STATE;
- }
- else {
- RSSIInitState = currentRadioState;
- call RSSIADC.getData();
- }
- }
- break;
-
- case PULSE_CHECK_STATE:
- atomic{
- uint8_t done = 0;
- uint16_t threshold = call GetSquelch();
- threshold = threshold - (call GetSquelch() >> 2);
- if(data > threshold){
- // adjust the noise floor level
- atomic usTempSquelch = data;
- post adjustSquelch();
-
- }else if(pulse_check_count > 5){
- //go to the idle state since no outliers were found
- call CC1000Control.RxMode();
- RadioState = IDLE_STATE;
- call SpiByteFifo.rxMode(); // SPI to miso
- call SpiByteFifo.enableIntr(); // enable spi interrupt
- post IdleTimerTask();
- done = 1;
-
- }else {
- call CC1000Control.RxMode();
- if(call RSSIADC.getData()){
- TOSH_uwait(80);
- pulse_check_count ++;
- done = 1;
- }
- pulse_check_sum ++;
- call CC1000StdControl.stop();
- }
- // changed here for hcl optimization
- if (bTxPending && (!enableHCL || !IsHCL(currentSlot))) { // bug fixed by Dr. Rhee
- //go to the idle state since no outliers were found
- call CC1000Control.RxMode();
- RadioState = IDLE_STATE;
- call SpiByteFifo.rxMode(); // SPI to miso
- call SpiByteFifo.enableIntr(); // enable spi interrupt
- post IdleTimerTask();
- done = 1;
- }
- if(done == 0){
- post SleepTimerTask();
- RadioState = POWER_DOWN_STATE;
- call SpiByteFifo.disableIntr();
- }
- }
- //go to the power down state
- break;
- default:
- }
- }
- return SUCCESS;
- }
- // XXX:JP- for testing the mac layer squlech value
- async command uint16_t GetSquelch() {
- return usSquelchVal;
- }
- // XXX:JP- for testing the mac layer power consumption
- async command uint16_t GetPower() {
- return power_sum;
- }
- async command uint16_t GetDataSent() {
- return dataSent;
- }
- async command result_t ResetDataSent() {
- dataSent = 0;
- return SUCCESS;
- }
- async command uint16_t GetPower_tx() {
- return tx_sum;
- }
- async command uint16_t GetPower_rx() {
- return rx_sum;
- }
- async command uint16_t GetPower_sp() {
- return sp_sum;
- }
- async command result_t ResetPower() {
- power_sum = 0;
- pulse_check_sum = 0;
- send_sum = 0;
- receive_sum = 0;
- sp_sum = 0;
- tx_sum = 0;
- rx_sum = 0;
- return SUCCESS;
- }
- async command result_t MacControl.enableAck() {
- atomic bAckEnable = TRUE;
- return SUCCESS;
- }
- async command result_t MacControl.disableAck() {
- atomic bAckEnable = FALSE;
- return SUCCESS;
- }
- async command result_t MacControl.enableCCA() {
- atomic bCCAEnable = TRUE;
- return SUCCESS;
- }
- async command result_t MacControl.disableCCA() {
- atomic bCCAEnable = FALSE;
- return SUCCESS;
- }
- // ***Not yet implemented
- async command TOS_MsgPtr MacControl.HaltTx() {
- return 0;
- }
- // Default events for radio send/receive coordinators do nothing.
- // Be very careful using these, you'll break the stack.
- default async event void RadioSendCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset,
- TOS_MsgPtr msgBuff) { }
- default async event void RadioSendCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
- default async event void RadioSendCoordinator.blockTimer() { }
- default async event void RadioReceiveCoordinator.startSymbol(uint8_t bitsPerBlock, uint8_t offset,
- TOS_MsgPtr msgBuff) { }
- default async event void RadioReceiveCoordinator.byte(TOS_MsgPtr msg, uint8_t byteCount) { }
- default async event void RadioReceiveCoordinator.blockTimer() { }
- default async event int16_t MacBackoff.initialBackoff(TOS_MsgPtr m){
- return (call Random.rand() & 0x1F) + 1;
- }
- default async event int16_t MacBackoff.congestionBackoff(TOS_MsgPtr m){
- congBackOffs++;
- return (call Random.rand() & 0xF) + 1;
- }
- /**************SClock Interface********/
- async event result_t SClock.syncDone(){
- if(needTimeSync){
- GTime loctime;
- uint32_t globalTimeStamp, slotOffset;
- call SClock.getTime(&loctime);
- globalTimeStamp = (uint32_t)(loctime.mticks * 568.889 + loctime.sticks * 0.00868056); //in ms
- slotOffset = (uint32_t) (1.024 * (slotSize - (globalTimeStamp % slotSize))); // in timer units .976562 = 1000/1024
- slotNum = (uint32_t) (globalTimeStamp/slotSize);
- currentSlot = slotNum & (localFrameLength - 1);
- globalSlot = slotNum & (globalFrameLength - 1);
- if(currentMAC == ZMAC)
- call TDMATimer.start(TIMER_ONE_SHOT, slotOffset);
- needTimeSync = FALSE;
- }
- return SUCCESS;
- }
- async event result_t SClock.fire(uint16_t mticks){ return SUCCESS; }
- }