⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smac.cc

📁 无线传感器网络经典MAC协议SMAC协议源码
💻 CC
📖 第 1 页 / 共 5 页
字号:
    Tcl& tcl = Tcl::instance();
    tcl.evalf("Mac/SMAC set syncFlag_");
    if (strcmp(tcl.result(), "0") != 0)  
        syncFlag_ = 1;              // syncflag is set; use sleep-wakeup cycle


    tcl.evalf("Mac/SMAC set selfConfigFlag_");
        if (strcmp(tcl.result(), "0") != 0)
                selfConfigFlag_ = 1;              // autoflag is set; user can not configure the schedule start time

    
    // User can specify the duty cycle
    tcl.evalf("Mac/SMAC set dutyCycle_");
    if (strcmp(tcl.result(), "0") != 0){
                bind_bw("dutyCycle_", &dutyCycle_);
                printf("dutyCyle=%f\n", dutyCycle_);
    
    }
        else {
                  dutyCycle_ = SMAC_DUTY_CYCLE;
                  printf("dutyCyle=%f\n", dutyCycle_);
    }

    if (!syncFlag_)
        txData_ = 0;
  
    else {
        // Calculate sync/data/sleeptime based on duty cycle
        // all time in ms
        syncTime_ = difs_ + slotTime_ * SYNC_CW + SEC2CLKTICK(durSyncPkt_) + guardTime_;
#ifdef JOURNAL_PAPER
                // added time for overhearing CTS so that can do adaptive listen
                dataTime_ = difs_ + slotTime_ * DATA_CW + SEC2CLKTICK(durCtrlPkt_) + PROC_DELAY + sifs_ + SEC2CLKTICK(durCtrlPkt_) + guardTime_;
#else
        dataTime_ = difs_ + slotTime_ * DATA_CW + SEC2CLKTICK(durCtrlPkt_) + guardTime_;
#endif
        listenTime_ = syncTime_ + dataTime_;
        cycleTime_ = listenTime_ * 100 / dutyCycle_ + 1;
        sleepTime_ = cycleTime_ - listenTime_;
    
        //printf("cycletime=%d, sleeptime=%d, listentime=%d\n", cycleTime_, sleepTime_, listenTime_);


        for (int i=0; i< SMAC_MAX_NUM_SCHEDULES; i++) {
            mhCounter_[i] = new SmacCounterTimer(this, i);
            mhCounter_[i]->syncTime_ = syncTime_;
            mhCounter_[i]->dataTime_ = dataTime_;
            mhCounter_[i]->listenTime_ = listenTime_;
            mhCounter_[i]->sleepTime_ = sleepTime_;
            mhCounter_[i]->cycleTime_ = cycleTime_;
    	}

        // printf("syncTime= %d, dataTime= %d, listentime = %d, sleepTime= %d, cycletime= %d\n", syncTime_, dataTime_, listenTime_, sleepTime_, cycleTime_);

        // listen for a whole period to choose a schedule first
        //double cw = (Random::random() % SYNC_CW) * slotTime_sec_ ;
  
        // The foll (higher) CW value allows neigh nodes to follow a single schedule
        // double w = (Random::random() % (SYNC_CW)) ;
        // double cw = w/10.0;
        double c = CLKTICK2SEC(listenTime_) + CLKTICK2SEC(sleepTime_);
        double s = SYNCPERIOD + 1;
        double t = c * s ;
        //mhGene_.sched(t + cw);

        if ( selfConfigFlag_ == 1) {
#ifdef JOURNAL_PAPER
                adapTime_ = dataTime_;
                mhGene_.sched(t);
                                                                                                                                                            
                //start setting timer for update neighbor list
                //printf("SMAC_UPDATE_NEIGHB_PERIOD: ............node %d %d at %.6f\n", index_, SMAC_UPDATE_NEIGHB_PERIOD, Scheduler::instance().clock());
                mhUpdateNeighb_.sched(SMAC_UPDATE_NEIGHB_PERIOD);
                //dump();
#else
        mhGene_.sched(t);
#endif
    	}
    }
}

void SMAC::setMySched(Packet *pkt) 
{
    // set my schedule and put it into the first entry of schedule table
    state_ = IDLE;
    numSched_ = 1;
    schedTab_[0].numPeriods = 0;
    schedTab_[0].txData = 0;
    schedTab_[0].txSync = 1; // need to brdcast my schedule
  
    if (pkt == 0) { // freely choose my schedule
#ifdef JOURNAL_PAPER
                //printf("#############################################################\n");
                //printf(" %d is choosing its own shedule %d \n", index_, index_);
                //printf("#############################################################\n");
                schedState_++;
                mhCounter_[0]->sched(CLKTICK2SEC(listenTime_+index_*10));
                schedTab_[0].syncNode = index_;
#else
        mhCounter_[0]->sched(CLKTICK2SEC(listenTime_));
#endif
        mySyncNode_ = index_; // myself
        currSched_ = 0;
        //sendSYNC();  
    
    } else { // follow schedule in syncpkt
    
        struct smac_sync_frame *pf = (struct smac_sync_frame *)pkt->access(hdr_mac::offset_);

        mhCounter_[0]->sched(pf->sleepTime);
#ifdef JOURNAL_PAPER
                mySyncNode_ = pf->syncNode;
                //printf("#############################################################\n");
                //printf("%d receives SYNC packet from %d and starts following shedule %d \n", index_, pf->srcAddr, pf->syncNode);
                //printf("#############################################################\n");
                schedTab_[0].numNodes++;  // 2 nodes on this schedule now
                schedTab_[0].syncNode = pf->syncNode;
                schedState_++;
                                                                                                                                                            
                //add node in my neighbor list
                neighbList_[0].nodeId = pf->srcAddr;
                neighbList_[0].schedId = 0;
                neighbList_[0].active = 1;
                neighbList_[0].state = pf->state;
#else
        mySyncNode_ = pf->srcAddr;    
        //add node in my neighbor list
        neighbList_[0].nodeId = mySyncNode_;
        neighbList_[0].schedId = 0;
#endif
        numNeighb_ = 1;
    }
}



int SMAC::command(int argc, const char*const* argv)
{
    if (argc == 3) {
        if (strcmp(argv[1], "log-target") == 0) {
            logtarget_ = (NsObject*) TclObject::lookup(argv[2]);
            if(logtarget_ == 0)
                return TCL_ERROR;
            return TCL_OK;
    	}
        else if ( selfConfigFlag_ != 1) {
            if (strcmp(argv[1], "schedule-start-time") == 0) {

                            startTime_ = strtod(argv[2],NULL);

                            // set up schedule
                            state_ = IDLE;
                            numSched_ = 1;
                            schedTab_[0].numPeriods = SYNCPERIOD;
                            schedTab_[0].txData = 0;
                            schedTab_[0].txSync = 1; // need to brdcast my schedule

                            // schedule starts up with listen time (sync+data)
                            // need to caculate time to sleep

                            startTime_ = startTime_ + listenTime_;
                            if ( startTime_ >= cycleTime_ )
                                    startTime_ = startTime_ - cycleTime_;

                            mhCounter_[0]->sched(CLKTICK2SEC(startTime_));
                            mySyncNode_ = index_; // myself

                            currSched_ = 0;

                            return TCL_OK;
    	
                    }

    	}
    }

    return Mac::command(argc, argv);

}

#ifdef JOURNAL_PAPER
void SMAC::adaptiveListen()
{
        // adaptively wake-up at the end of current transmission. Will try to
        // send only if the buffered packet is unicast. Since my next-hop
        // neighbor may not be aware of the Tx of my previous-hop neighbor,
        // broadcast now is unreliable
        //printf("adaptiveListen set AdaptiveTimer: node %d scheduletime: %f adapTime_: %d time:%.9f \n", index_, mhCounter_[0]->value_, adapTime_, Scheduler::instance().clock());
        mhAdap_.resched(CLKTICK2SEC(adapTime_)); // set timer to bring me back to sleep
        adaptiveListen_ = 1;
        if (state_ == SLEEP) {
                //printf("adaptiveListen wakeup: node %d scheduletime: %f time:%.9f \n", index_, mhCounter_[0]->value_, Scheduler::instance().clock());
                wakeup();
        }
         else {
        }
                                                                                                                                                            
        if ( schedTab_[0].txData == 1 && sendAddr == UNICAST_ADDR){
                adapSend_ = 1;
                checkToSend();
        }
}
#endif

// XXXX smac handler functions

void SMAC::handleSendTimer() {
    assert(pktTx_);
  
    struct hdr_smac *sh = HDR_SMAC(pktTx_);
  
    // Packet tx is done so radio should go back to idle
    radioState_ = RADIO_IDLE;
    tx_active_ = 0;
  
    switch(sh->type) {
    
    case RTS_PKT:
        sentRTS(pktTx_);
        break;

    case CTS_PKT:
        sentCTS(pktTx_);
        break;
    
    case DATA_PKT:
        sentDATA(pktTx_);
        break;
  
    case ACK_PKT:
        sentACK(pktTx_);
        break;
    case SYNC_PKT:
        sentSYNC(pktTx_);
        break;
    default:
        fprintf(stderr, "unknown mac pkt type, %d\n", sh->type);
        break;
    }
  
    pktTx_ = 0;
}


void SMAC::handleRecvTimer() {
    assert(pktRx_);
  
    struct hdr_cmn *ch = HDR_CMN(pktRx_);
    struct hdr_smac *sh = HDR_SMAC(pktRx_);

    if (state_ == SLEEP) {

        // Bug fixed here. a collision might happen just now, need to clear the mac_collision_ flag, otherwise the node won't receive any following packet

        if (mac_collision_) {
                    discard(pktRx_, DROP_MAC_COLLISION);
                    mac_collision_ = 0;
                    updateNav(CLKTICK2SEC(eifs_));

                    if (state_ == CR_SENSE)
                            sleep(); // have to wait until next wakeup time
                    else
                            radioState_ = RADIO_IDLE;

                    goto done;
                }

        discard(pktRx_, DROP_MAC_SLEEP);
        radioState_ = RADIO_SLP;
        goto done;
    }
  
    // if the radio interface is tx'ing when this packet arrives
    // I would never have seen it and should do a silent discard 
  
    if (radioState_ == RADIO_TX) {
        Packet::free(pktRx_);
        goto done;
    }
  
    if (mac_collision_) {
        discard(pktRx_, DROP_MAC_COLLISION);
        mac_collision_ = 0;
        updateNav(CLKTICK2SEC(eifs_));
    
        if (state_ == CR_SENSE) 
            sleep(); // have to wait until next wakeup time
        else 
            radioState_ = RADIO_IDLE;
    
        goto done;
    }
  
    if (ch->error()) {
        Packet::free(pktRx_);
        updateNav(CLKTICK2SEC(eifs_)); 

        if (state_ == CR_SENSE) 
            sleep();
        else 
            radioState_ = RADIO_IDLE;
      
        goto done;
    }
  
    // set radio from rx to idle again
    radioState_ = RADIO_IDLE;

    switch (sh->type) {
    case DATA_PKT:
        handleDATA(pktRx_);
        break;
    case RTS_PKT:
        handleRTS(pktRx_);
        Packet::free(pktRx_);
        break;
    case CTS_PKT:
        handleCTS(pktRx_);
        Packet::free(pktRx_);
        break;
    case ACK_PKT:
        handleACK(pktRx_);
        Packet::free(pktRx_);
        break;
    case SYNC_PKT:
        handleSYNC(pktRx_);
        Packet::free(pktRx_);
        break;
    default:
        fprintf(stderr, "Unknown smac pkt type, %d\n", sh->type);
        break;
    }
  
 done:
    pktRx_ = 0;
  
}

void SMAC::handleGeneTimer() 
{
  
    if (syncFlag_) {
        // still in choose-schedule state
        if (numSched_ == 0) {
            setMySched(0); // I'm the primary synchroniser
            return;
    	} 
    }
    if (state_ == WAIT_CTS) {  // CTS timeout
        if (numRetry_ < SMAC_RETRY_LIMIT) {
            numRetry_++;
            // wait until receiver's next wakeup
            state_ = IDLE;
#ifdef JOURNAL_PAPER

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -