CC1000RadioIntM.nc
上传用户:joranyuan
上传日期:2022-06-23
资源大小:3306k
文件大小:61k
- includes crc;
- includes CC1000Const;
- includes NeighborInfo;
- 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 result_t ResetPower();
- }
- 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 "SODebug.h"
- #define SINK 3
- #define MIN_TRUST 1
- #define MAX_TRUST 8
- #define AM_HELLO 31
- #define CSLOTS_PER_TDMA 125
- #define CSLOT_SIZE 0.4
- #define MAX_NEIGHBORS 20
- #define ECNCHECKPERIOD 16
- #define ECNSENDPERIOD 96 //in terms of TDMA slots
- #define ECNEXPIREPERIOD 192 //in terms of TDMA slots
- #define ECNFORWARDPERIOD 1 //in terms of global frames
- #define ECNMINPACKETS 10
- #define HOPCOUNT 0
- #define NEXTHOP 1
- #define ECNTYPE 222
- #define SYNCTYPE 223
- #define SYNC_PERIOD 100
- #define TRUST_FACTOR 1
- #define SENDERADDRESS 2
- //#define SELECTHCL 1
- //#define SELECTNDC 0
- //#define DEBUG
- 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 = 8888,
- SEND_MA_COUNT = 7200,
- PREAMBLE_LENGTH_TO_BASE = 8,
- RECEIVE_MA_COUNT = 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, recvSync;
- GTime currDiff;
- uint8_t currSign;
- //modified by Mahesh
- enum {
- BMAC,
- HYMAC
- };
- enum{
- T_O = 8,
- T_NO = 32
- };
- enum{
- MAX_VAL = 0xFFFF
- };
- enum{
- POSITIVE = 1,
- NEGATIVE = 2,
- ZERO = 3
- };
-
- /*struct neighborinfo
- {
- uint8_t id;
- uint8_t owner;
- uint8_t local_fsize;
- }*/
- struct neighborinfo twohopneighbors[MAX_NEIGHBORS];
-
- uint8_t current_mac = BMAC; // select current MAC .. default must be BMAC and change to HYMAC after DRAND completes
- uint16_t no_of_slots; // to be obtained from DRAND
- uint16_t slot_size;
- uint16_t next_hop;
- uint16_t own_slot;
- uint16_t framesize;
- uint16_t slots_since_ecnsend;
- uint16_t slots_since_ecnrecv;
- uint16_t slots_since_ecncheck;
- uint8_t frames_since_forward;
- uint16_t global_fsize;
- uint32_t global_slot;
- uint16_t global_timestamp = 1000; // DRAND passes on the latest value of the TPSN mticks value upon completion
- uint16_t current_time = 0; //number of interrupts since global timestamp
- uint16_t current_slot = 0;
- uint16_t next_slot = 1;
- uint16_t packets_sent;
- uint16_t pkts_last_sync = 0;
- double current_loss;
- uint16_t recvacks;
- uint16_t congbackoffs;
- uint16_t ecncheckfreq;
- uint16_t ecnexpirefreq;
- double ecnthreshold;
- double avgloss;
- uint32_t curHCLlist = 0;
- uint32_t prevHCLlist = 0;
- uint16_t ecnqueuesize;
- uint8_t neighbors[MAX_NEIGHBORS];
- uint8_t onehopneighborcount;
- uint8_t twohopneighborcount;
- uint16_t ecnfwdcount = 0;
- uint16_t ecnsentcount = 0;
- double alpha;
- bool HCLselect;
- bool ack_orig;
- bool ecnpending;
- bool ecnforward;
- bool enableHCL;
- bool enableNDC;
- bool check_NDC;
- bool wait_HCL;
- bool pureHCL;
- TOS_Msg ecnMsg;
- TOS_Msg ecnForwardMsg;
- TOS_Msg syncMsgHdr;
- //ecnMsg.addr = TOS_BCAST_ADDR;
- //ecnMsg.type = 33;
- //ecnMsg.data[0] = 0;
- /*****/
- 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;
- 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;
- uint8_t receiveCount;
- ///**********************************************************
- //* 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
- }
- */
- 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;
- }
- }
- 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 glo_slot) {
- uint32_t value = 1;
- uint32_t check = value<<glo_slot;
- uint8_t flag = 0;
- atomic
- {
- if((check & curHCLlist) == check)
- flag = 1;
-
- else
- flag = 0;
- }
-
- // SODbg(DBG_USR2,"flag:%i slot:%i check:%i list:%i",flag,glo_slot,check,curHCLlist);
- if(flag == 1)
- return(TRUE);
- else
- return(FALSE);
- }
- bool IsNDC(){
- GTime loctime;
- uint16_t slot_offset;
- call SClock.getTime(&loctime);
- global_timestamp = (uint16_t)(loctime.mticks * 568.8 + loctime.sticks * 0.00868); //in ms
- //SODbg(DBG_USR2, "Current time is %un", global_timestamp);
- if((enableNDC == TRUE) && (enableHCL == TRUE) && (IsHCL(next_slot))){
- slot_offset = (uint16_t)(global_timestamp)%(slot_size);
- slot_offset = (slot_size - slot_offset)/CSLOT_SIZE;
- if((txlength + preamblelen + 2) > slot_offset)
- return TRUE;
- else
- return FALSE;
- } else{
- return FALSE;
- }
- }
- 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 Blacklist(uint8_t ECN_slot,uint8_t ECN_fsize)
- {
- uint8_t black_slot;
- // SODbg(DBG_USR2,"%i %i %i",ECN_fsize,ECN_slot,no_of_slots);
- // SODbg(DBG_USR2,"Curr list is %i",curHCLlist);
- atomic {
- if(ECN_fsize <= global_fsize) {
- black_slot = ECN_slot;
- while(black_slot < global_fsize) {
- curHCLlist = curHCLlist | (1<<black_slot);
- black_slot = black_slot + ECN_fsize;
-
- // SODbg(DBG_USR2,"Vector: %i",curHCLlist);
- }
- // SODbg(DBG_USR2,"list:%i",curHCLlist);
- }
-
- }
-
- }
- /*
- void updateAverageDiff(GTime diff, uint8_t sign){ //EWMA of time diff
- uint8_t newSign;
- recvSync++;
- if((currSign == POSITIVE && sign == POSITIVE) ||
- (currSign == NEGATIVE && sign == NEGATIVE)){
- AddTime(&currDiff, &diff, &currDiff);
- SODbg(DBG_USR2, "currDiff = %u, currSign = %un", currDiff, currSign);
- }else if((currSign == NEGATIVE && sign == POSITIVE) ||
- (currSign == POSITIVE && sign == NEGATIVE)){
- newSign = ModSubTime(&currDiff, &currDiff, &diff);
- if(newSign == POSITIVE)
- currSign = currSign; // no change in sign
- else
- currSign = sign; // else sign is same as new value
- SODbg(DBG_USR2, "currDiff = %u, currSign = %un", currDiff, currSign);
- }
- }
- */
- void adjustTime(){
- uint16_t sign, i, trust;
- GTime loctime, timeStamp, diff, correctedTime;
- struct syncMsgType* syncMsgPtr;
- syncMsgPtr = (struct syncMsgType *) rxbufptr->data;
- timeStamp.mticks = syncMsgPtr->mticks;
- timeStamp.sticks = syncMsgPtr->sticks;
- trust = syncMsgPtr->trust;
- call SClock.getTime(&loctime);
- #ifdef DEBUG
- SODbg(DBG_USR2, "*********************************************n");
- SODbg(DBG_USR2, "From: %i R_STICKS = %u, R_MTICKS = %u, MY_STICKS = %u, MY_MTICKS = %un",
- syncMsgPtr->sender, timeStamp.sticks, timeStamp.mticks, loctime.sticks, loctime.mticks);
- #endif
- sign = ModSubTime(&diff, &timeStamp, &loctime);
- #ifdef DEBUG
- if(diff.mticks == 0 && TOS_LOCAL_ADDRESS == SINK)
- SODbg(DBG_USR2, "Converged !!!");
- #endif
- // update difference average
- //updateAverageDiff(diff, sign);
-
- if(trust < MIN_TRUST)
- trust = MIN_TRUST;
- if(trust < MAX_TRUST){
- for(i = 0; i < trust; i++){
- DivTime2(&diff, &diff);
- //SODbg(DBG_USR2, "diff = %u, %u, %u n", diff.mticks, diff.sticks, trust);
- }
- call SClock.setTime(sign, &diff);
- call SClock.getTime(&loctime);
- //SODbg(DBG_USR2, "sign = %u, Adjusted Time MY_STICKS = %u, MY_MTICKS = %un",
- // sign, loctime.sticks, loctime.mticks);
- }
- }
-
- task void PacketRcvd() {
- TOS_MsgPtr pBuf;
- atomic {
- receiveCount++;
- if(pkts_last_sync > SYNC_PERIOD){
- atomic{
- ack_orig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&syncMsgHdr);
- pkts_last_sync = 0;
- }
- pkts_last_sync++;
- rxbufptr->time = 0;
- pBuf = rxbufptr;
- }
-
- if(pBuf->addr == ECNTYPE)
- {
- #ifdef DEBUG
- SODbg(DBG_USR2,"Received %i hop ECN from %i, deciding whether significant..n", pBuf->data[HOPCOUNT],pBuf->data[SENDERADDRESS]);
- #endif
- }
- if(current_mac == HYMAC && pBuf->addr == ECNTYPE && pBuf->crc != 0
- && pBuf->data[SENDERADDRESS]!= TOS_LOCAL_ADDRESS) //Message is an ECN
- {
-
- if((pBuf->data[HOPCOUNT] == 0) && (pBuf->data[NEXTHOP] == TOS_LOCAL_ADDRESS))
- {
- #ifdef DEBUG
- SODbg(DBG_USR2,"Received one-hop ECN from %in",pBuf->data[SENDERADDRESS]);
- #endif
- atomic
- {
- ecnForwardMsg.data[HOPCOUNT] = (uint8_t) (pBuf->data[HOPCOUNT] + 1);
- ecnForwardMsg.data[NEXTHOP] = (uint8_t) (next_hop);
- ecnForwardMsg.data[SENDERADDRESS] = (uint8_t) (TOS_LOCAL_ADDRESS);
- frames_since_forward = 0;
- if(!bTxBusy)
- {
- ack_orig = bAckEnable;
- bAckEnable = FALSE;
- call Send.send(&ecnForwardMsg); //take care of case where we are not currently sending
- #ifdef DEBUG
- // SODbg(DBG_USR2,"Forwarded ECNn");
- #endif
- }
- else
- ecnforward = TRUE;
- }
- }
- else if(pBuf->data[HOPCOUNT] == 1) //check if two-hop ECN
- {
- // SODbg(DBG_USR2,"Received two hop ECN from %in",pBuf->data[SENDERADDRESS]);
- #ifdef DEBUG
- SODbg(DBG_USR2,"Received two hop ECN from %in",pBuf->data[SENDERADDRESS]);
- #endif
-
- //Take action, blacklist given slot
- atomic enableHCL = TRUE;
- if(pBuf->data[SENDERADDRESS] == next_hop) //check forwarding node's address
- {
- //suppress ECN
- #ifdef DEBUG
- SODbg(DBG_USR2,"Suppressed own ECNn");
- #endif
-
- atomic ecnpending = FALSE;
- slots_since_ecnsend = 0;
- slots_since_ecnrecv = 0;
- }
- // Blacklist(pBuf->data[1],pBuf->data[3]);
-
- }
-
- }
- else if(pBuf->addr != SYNCTYPE &&
- (TOS_LOCAL_ADDRESS != SINK || (pBuf->type > 7) )) // SINK = 2
- {
- #ifdef DEBUG
- // SODbg(DBG_USR2,"Received packet of type %un",pBuf->addr);
- #endif
- pBuf = signal Receive.receive((TOS_MsgPtr)pBuf);
- }
-
- atomic {
- 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->addr != ECNTYPE && txbufptr->addr != SYNCTYPE)
- signal Send.sendDone((TOS_MsgPtr)pBuf,SUCCESS);
- atomic bTxBusy = FALSE;
- if(pkts_last_sync > SYNC_PERIOD){
- atomic
- {
- ack_orig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&syncMsgHdr);
- pkts_last_sync = 0;
- }
-
- if(ecnforward == TRUE)
- {
- atomic
- {
- ack_orig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&ecnForwardMsg);
- atomic ecnforward = FALSE;
- #ifdef DEBUG
- // SODbg(DBG_USR2,"Forwarded ECNn");
- #endif
-
- }
- if(ecnpending == TRUE)
- {
- atomic
- {
- ack_orig = bAckEnable;
- bAckEnable = FALSE;
- }
- call Send.send(&ecnMsg);
- atomic ecnpending = FALSE;
- atomic slots_since_ecnsend = 0;
- #ifdef DEBUG
- SODbg(DBG_USR2,"Sent own ECNn");
- #endif
- }
- }
-
-
- ///**********************************************************
- //* Exported interface functions
- //**********************************************************/
- /*
- command uint16_t SetDrand.getDiffMticks(){
- SODbg("Getting Mticks = %un", currDiff.mticks);
- return currDiff.mticks/recvSync;
- }
- command uint16_t SetDrand.getDiffSticks(){
- SODbg("Getting Mticks = %un", currDiff.sticks);
- return currDiff.sticks/recvSync;
- }
- */
- command result_t SetDrand.Set(uint16_t mval, uint16_t sval,uint8_t num_nodes,uint8_t hop,/*uint8_t n1count,uint8_t neighbors1hop[],*/uint8_t n2count,struct neighborinfo neighbors2hop[]) {
- // command result_t SetDrand.Set(uint16_t mval,uint16_t sval,uint8_t num_nodes){
- uint16_t slot_offset = 0;
- uint8_t i = 0;
- if(num_nodes > 16)
- no_of_slots = 32;
- else if(num_nodes > 8)
- no_of_slots = 16;
- else if(num_nodes > 4)
- no_of_slots = 8;
- else if(num_nodes > 2)
- no_of_slots = 4;
- else
- no_of_slots = 2;
-
- no_of_slots = num_nodes;
- framesize = no_of_slots * slot_size;
- //current_mac = HYMAC;
- global_timestamp = (uint16_t)(mval * 568.8 + sval * 0.00868) ; //in ms
- current_slot = (uint16_t)(global_timestamp % framesize)/(slot_size);
- slot_offset = (uint16_t)(global_timestamp % framesize)%(slot_size);
- global_slot = (uint16_t)(global_timestamp % (global_fsize * slot_size))/(slot_size);
- next_slot = ((global_slot + 1)%global_fsize);
-
-
- next_hop = hop;
- own_slot = TOS_LOCAL_ADDRESS;
- // ecnMsg.data[1] = own_slot;
-
- /* onehopneighborcount = n1count;
- for(i=0;i<n1count;i++)
- neighbors[i] = neighbors1hop[i];*/
- twohopneighborcount = n2count;
- for(i=0;i<n2count;i++)
- {
- twohopneighbors[i] = neighbors2hop[i];
- Blacklist(twohopneighbors[i].owner,twohopneighbors[i].local_fsize);
- }
-
- call TDMATimer.start(TIMER_ONE_SHOT,slot_size - slot_offset);
- #ifdef DEBUG
- // SODbg(DBG_USR2,"Started timer slotsize - offset is %in",slot_size - slot_offset);
- #endif
- return SUCCESS;
- }
- command result_t StdControl.init() {
- char i;
- // atomic own_slot = TOS_LOCAL_ADDRESS;
- 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;
- receiveCount=0;
- alpha = 0.25;
- recvacks = 0;
- congbackoffs = 0;
- packets_sent = 0;
- current_loss = 0.0;
- avgloss = 0.0;
- ecnqueuesize = 0;
- curHCLlist = 0;
- prevHCLlist = 0;
- global_fsize = 32;
- ack_orig = bAckEnable;
- ecnpending = FALSE;
- ecnforward = FALSE;
- enableHCL = FALSE; // changed to FALSE for LCL by Ajit
- //enableNDC = SELECTNDC;
- enableNDC = FALSE;
- check_NDC = FALSE;
- wait_HCL = FALSE;
- pureHCL = FALSE;
- //HCLselect = SELECTHCL; // changed to FALSE by Ajit for LCL
- HCLselect = TRUE; // changed to FALSE by Ajit for LCL
- no_of_slots = 4; //2; //these must be set by Drand in SetDrand.Set
- own_slot = TOS_LOCAL_ADDRESS;
- slot_size = 50; //ms
- framesize = no_of_slots * slot_size;
- slots_since_ecnsend = 0;
- slots_since_ecnrecv = 0;
- slots_since_ecncheck = 0;
- frames_since_forward = 0;
- next_hop = TOS_LOCAL_ADDRESS + 1;
-
- //modified
- ecnMsg.type = 31; //set ecnMsg headers
- ecnMsg.addr = ECNTYPE; //ECN Indicator;
- ecnMsg.length = 3;
- ecnMsg.group = 125;
- ecnMsg.crc = 0;
- ecnForwardMsg.type = 31;
- ecnForwardMsg.addr = ECNTYPE;
- ecnForwardMsg.length = 3;
- ecnForwardMsg.group = 125;
- ecnForwardMsg.crc = 0;
- ecnMsg.data[HOPCOUNT] = (uint8_t) 0; //hopcount
- ecnMsg.data[NEXTHOP] = (uint8_t) next_hop; //parent node
- ecnMsg.data[SENDERADDRESS] = (uint8_t) TOS_LOCAL_ADDRESS;
-
- ecncheckfreq = 10000; //these parameters must be specified by application
- ecnexpirefreq = 500; // write new interfaces to set these
- ecnthreshold = 3.0;
- syncMsgHdr.type = 31; //set syncMsg headers
- syncMsgHdr.addr = SYNCTYPE; //SYNC Indicator;
- syncMsgHdr.length = 7; // mticks, sticks, trust, sender
- syncMsgHdr.group = 125;
- syncMsgHdr.crc = 0;
- currDiff.mticks = 0;
- currDiff.sticks = 0;
- currSign = POSITIVE;
- recvSync = 0;
- }
- 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();
-
- init_debug();
- LocalAddr = TOS_LOCAL_ADDRESS;
- return SUCCESS;
- }
-
- //async command uint8_t LowPowerListening.GetReceiveCount() {
- // return receiveCount;
- //}
- /**
- * 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) {
- 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;
- }
- //added by Mahesh
- event result_t TDMATimer.fired()
- {
- #ifdef DEBUG
- // SODbg(DBG_USR2,"Timer fired");
- #endif
- if(current_mac == BMAC)
- atomic current_mac = HYMAC;
-
- call TDMATimer.start(TIMER_ONE_SHOT,slot_size);
- atomic
- {
- current_slot = (current_slot + 1)%(no_of_slots);
- if(HCLselect)
- {
- slots_since_ecnsend ++;
- slots_since_ecnrecv ++;
- slots_since_ecncheck++;
- if(packets_sent > ECNMINPACKETS && slots_since_ecncheck >= ECNCHECKPERIOD)
- {
- current_loss = (double)congbackoffs/packets_sent;
- avgloss = alpha*(current_loss) + (1-alpha)*avgloss;
- slots_since_ecncheck = 0;
- #ifdef DEBUG
- SODbg(DBG_USR2,"Congestion Statistics: %i / %in",congbackoffs,packets_sent);
- #endif
-
- if(avgloss > ecnthreshold && slots_since_ecnsend >= ECNSENDPERIOD)
- {
- #ifdef DEBUG
- SODbg(DBG_USR2,"Setting ECN flagn");
- #endif
- ecnMsg.data[NEXTHOP] = (uint8_t) next_hop;
-
- if(!pureHCL)
- ecnpending = TRUE; //remember to uncomment
-
- // frames_since_ecn = 0;
- }
- congbackoffs = 0;
- packets_sent = 0;
- }
- if(enableHCL && slots_since_ecnrecv >= ECNEXPIREPERIOD)
- {
- if(!pureHCL)
- enableHCL = FALSE;
- #ifdef DEBUG
- SODbg(DBG_USR2,"ECN expired, into LCL againn");
- #endif
- // slots_since_ecnrecv = 0;
- }
- global_slot = (global_slot + 1)%(global_fsize);
- #ifdef DEBUG
- // if(enableHCL)
- // SODbg(DBG_USR2,"Current slot %i **********************n",current_slot);
- #endif
-
- if(enableHCL && IsHCL(global_slot) && own_slot != current_slot)
- {
- wait_HCL = TRUE;
- #ifdef DEBUG
- SODbg(DBG_USR2,"Current slot %i HCLn",current_slot);
- #endif
- }
- else
- wait_HCL = FALSE;
-
- next_slot = (global_slot + 1)%(global_fsize);
- #ifdef DEBUG
- // SODbg(DBG_USR2,"next slot %u owner slot %un",next_slot,own_slot);
- #endif
- /*
- if(enableHCL && enableNDC && IsHCL(next_slot) && !wait_HCL)
- check_NDC = TRUE;
- else
- check_NDC= FALSE;
- */
-
- if(current_slot == own_slot)
- {
- #ifdef DEBUG
- // SODbg(DBG_USR2,"**********Owner Slot************* btxpending %i sMacDelay %in",bTxPending,sMacDelay);
- #endif
- sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
- }
- else{
- if(sMacDelay < 0)
- sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
- else{
- if(sMacDelay + T_O < (T_O + T_NO - 1))
- sMacDelay = sMacDelay + T_O;
- else
- sMacDelay = T_O + T_NO - 1;
- }
- }
- if(global_slot == own_slot) //global frame boundary, take action
- // processing for ecn
- {
-
- frames_since_forward ++;
- }
-
-
-
-
-
- }
- }
- 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;
-
-
-
- if (currentRadioState == DISABLED_STATE) {
- atomic {
- rxbufptr->length = 0;
- RadioState = IDLE_STATE;
- bTxPending = bTxBusy = FALSE;
- sMacDelay = -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;
- }
- else {
- bTxBusy = TRUE;
-
- txbufptr = pMsg;
- txlength = pMsg->length + (MSG_DATA_SIZE - DATA_LENGTH - 2);
- }
-
- // initially back off [1,32] bytes (approx 2/3 packet)
- if(bCCAEnable)
- sMacDelay = signal MacBackoff.initialBackoff(pMsg);
- else
- sMacDelay = 0;
- bTxPending = TRUE;
- currentRadioState = RadioState;
- }
- if (Result) {
- // if we're off, start the radio
- if (currentRadioState == POWER_DOWN_STATE) {
- // disable wakeup timer
- atomic RadioState = IDLE_STATE;
- 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 DEBUG
- // SODbg(DBG_USR2,"Sent packet in slot %in",current_slot);
- // SODbg(DBG_USR2, "ishcl = %u, isndc = %u n", IsHCL(current_slot),
- // IsNDC());
- #endif
- }
- break;
- case TXSTATE_SYNC:
- send_sum ++;
- NextTxByte = NSYNC_BYTE;
- RadioTxState = TXSTATE_DATA;
- TxByteCnt = -1;
- if(txbufptr->addr == SYNCTYPE){
- struct syncMsgType *syncMsgPtr = (struct 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) {
- 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 DEBUG
- // SODbg(DBG_USR2,"Came heren");
- #endif
- if (bAckEnable)
- RadioTxState = TXSTATE_WAIT_FOR_ACK;
-
- else {
- #ifdef DEBUG
- // SODbg(DBG_USR2,"came inside: current MAC: %i ackenabled :%i,ecnpending: %i ecnforward %i ecnSENT %in",current_mac,bAckEnable,ecnpending,ecnforward,sentECN);
- #endif
- packets_sent ++;
- call SpiByteFifo.rxMode();
- call CC1000Control.RxMode();
- RadioTxState = TXSTATE_DONE;
- }
- }
- break;
- case TXSTATE_WAIT_FOR_ACK:
- if(TxByteCnt == 1){
- // packets_sent ++;
- 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;
- // recvacks++ ;
- #ifdef DEBUG
- SODbg(DBG_USR2,"received ackn");
- #endif
- return SUCCESS;
- }
- }
- }
- if(TxByteCnt >= MAX_ACK_WAIT){
- txbufptr->ack = 0;
- // lostacks++;
- #ifdef DEBUG
- // SODbg(DBG_USR2,"did not receive ack %i %i %in",lostacks,packets_sent,avgloss * 100);
- #endif
-
- /***/
- RadioTxState = TXSTATE_DONE;
-
- }
-
- break;
- case TXSTATE_DONE:
- default:
- bTxPending = FALSE;
-
- if(txbufptr->addr == ECNTYPE || txbufptr->addr == SYNCTYPE){
- if(txbufptr->addr == ECNTYPE && txbufptr->data[HOPCOUNT] == 1)
- {
- #ifdef DEBUG
- SODbg(DBG_USR2,"Successfully forwarded ECNn");
- #endif
- }
- bAckEnable = ack_orig;
- }
- call SClock.getTime(&loctime);
- global_timestamp = (uint16_t)(loctime.mticks * 568.8 + loctime.sticks * 0.00868) ; //in ms
- //SODbg(DBG_USR2,"Sent Packet seqnum = %u at %un", txbufptr->data[1],
- //global_timestamp);
- if(post PacketSent()) {
- // If the post operation succeeds, goto Idle
- // otherwise, we'll try again.
- #ifdef DEBUG
- // SODbg(DBG_USR2,"Packet type %in",txbufptr->addr);
- #endif
- RadioState = IDLE_STATE;
- pkts_last_sync++;
- 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 ((enableHCL == FALSE) || (!IsHCL(current_slot))) {
- --sMacDelay;
- if ((bTxPending && (sMacDelay <= 0)) && !IsNDC()) {
- RadioState = PRETX_STATE;
- RSSIInitState = PRETX_STATE;
- bRSSIValid = FALSE;
- iRSSIcount = 0;
- PreambleCount = 0;
- call RSSIADC.getData();
- }
- }
- }
- }
- break;
- case PRETX_STATE:
- {
- receive_sum ++;
- if (((data_in == (0xaa)) || (data_in == (0x55)))) {
- // Back to the penalty box.
- sMacDelay = signal MacBackoff.congestionBackoff(txbufptr);
- 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) {
- 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->addr == SYNCTYPE){
- 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(bTxPending == TRUE){ // changes by Ajit
- if(current_slot == own_slot)
- sMacDelay = signal MacBackoff.congestionBackoff(rxbufptr);
- else{
- if(sMacDelay + T_O < (T_O + T_NO - 1))
- sMacDelay = sMacDelay + T_O;
- else
- sMacDelay = T_O + T_NO - 1;
- }
- // reset timer when time slot boundary
- }
- rxbufptr->strength = usRSSIVal;
- call SClock.getTime(&loctime);
- global_timestamp = (uint16_t)(loctime.mticks * 568.8 + loctime.sticks * 0.00868) ; //in ms
- /*
- if(rxbufptr->addr != SYNCTYPE)
- SODbg(DBG_USR2,"Received Packet from %u seqnum = %u at %un", rxbufptr->data[0],
- rxbufptr->data[1], global_timestamp);
- */
- 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 ++;
- 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;
- }
- 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;
- }*/
- }
- 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);
- 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();
- }
-
- if (bTxPending) { // 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 result_t ResetPower() {
- power_sum = 0;
- pulse_check_sum = 0;
- send_sum = 0;
- receive_sum = 0;
- }
- 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) {
- uint16_t backoff;
- if(current_mac == HYMAC)
- {
- /*
- // SODbg(DBG_USR2,"current slot is %i own slot %i",current_slot,own_slot);
- if(wait_HCL)
- {
- call SClock.getTime(&loctime);
- global_timestamp = (uint16_t)(loctime.mticks * 568.8 + loctime.sticks * 0.00868) ; //in ms
- slot_offset = (uint16_t)(global_timestamp % framesize)%(slot_size);
- slot_offset = (slot_size - slot_offset)/CSLOT_SIZE;
- if(next_slot == own_slot)
- return (call Random.rand() & (T_O - 1)) + 1 + slot_offset;
- else
- return (call Random.rand() & (T_NO-1)) + T_O + 1 + slot_offset;
- }
- else
- {
- */
- if(current_slot == own_slot)
- backoff = (call Random.rand() & (T_O - 1)) + 1;
- else
- backoff = (call Random.rand() & (T_NO - 1)) + 1 + T_O;
- /*
- if(check_NDC)
- {
- call SClock.getTime(&loctime);
- global_timestamp = (uint16_t)(loctime.mticks * 568.8 + loctime.sticks * 0.00868) ; //in ms
- slot_offset = (uint16_t)(global_timestamp % framesize)%(slot_size);
- slot_offset = (slot_size - slot_offset)/CSLOT_SIZE;
- if((txlength + preamblelen + 2) > slot_offset-backoff)
- backoff = slot_offset + slot_size * CSLOTS_PER_TDMA;
- }
- */
- return(backoff);
- //}
- }
- else //use 0 initial backoff for optimal BMAC performance
- return (call Random.rand() & 0x1F) + 1;
- }
- default async event int16_t MacBackoff.congestionBackoff(TOS_MsgPtr m) {
- uint16_t backoff;
- if(current_mac == HYMAC)
- {
- congbackoffs++;
- // SODbg(DBG_USR2,"current slot is %i own slot %i",current_slot,own_slot);
- /*
- if(wait_HCL)
- {
- call SClock.getTime(&loctime);
- global_timestamp = (uint16_t)(loctime.mticks * 568.8 + loctime.sticks * 0.00868) ; //in ms
- slot_offset = (uint16_t)(global_timestamp % framesize)%(slot_size);
- slot_offset = (slot_size - slot_offset)/CSLOT_SIZE;
- if(next_slot == own_slot)
- return (call Random.rand() & (T_O - 1)) + 1 + slot_offset;
- else
- return (call Random.rand() & (T_NO - 1)) + T_O + 1 + slot_offset;
- }
- else
- {
- */
- if(current_slot == own_slot)
- backoff = (call Random.rand() & (T_O - 1)) + 1;
- else
- backoff = (call Random.rand() & (T_NO - 1)) + 1 + T_O;
-
- /*
- if(IsHCL(next_slot))
- {
- call SClock.getTime(&loctime);
- global_timestamp = (uint16_t)(loctime.mticks * 568.8 + loctime.sticks * 0.00868) ; //in ms
- slot_offset = (uint16_t)(global_timestamp)%(slot_size);
- slot_offset = (slot_size - slot_offset)/CSLOT_SIZE;
- if((txlength + preamblelen + 2) > slot_offset)
- backoff = slot_offset + slot_size * CSLOTS_PER_TDMA;
- }
- */
- return(backoff);
-
- //}
- }
- else
- return (call Random.rand() & 0xF) + 1;
- }
- /**************SClock Interface********/
- async event result_t SClock.syncDone()
- {
- return SUCCESS;
- }
- async event result_t SClock.fire(uint16_t mticks)
- {
- return SUCCESS;
- }
- }