mrcl_wireless-phy.cc

00001 /* -*-  Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- 
00002  *
00003  * Copyright (c) 1996 Regents of the University of California.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. All advertising materials mentioning features or use of this software
00015  *    must display the following acknowledgement:
00016  *      This product includes software developed by the Computer Systems
00017  *      Engineering Group at Lawrence Berkeley Laboratory and the Daedalus
00018  *      research group at UC Berkeley.
00019  * 4. Neither the name of the University nor of the Laboratory may be used
00020  *    to endorse or promote products derived from this software without
00021  *    specific prior written permission.
00022  *
00023  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00024  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00027  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00028  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00029  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00032  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00033  * SUCH DAMAGE.
00034  *
00035  * $Header: /nfs/jade/vint/CVSROOT/ns-2/mac/wireless-phy.cc,v 1.25 2005/08/22 05:08:33 tomh Exp $
00036  *
00037  * Ported from CMU/Monarch's code, nov'98 -Padma Haldar.
00038  * wireless-phy.cc
00039  */
00040 #include "mrcl_wireless-phy.h"
00041 
00042 #include <math.h>
00043 
00044 #include <packet.h>
00045 
00046 #include <mobilenode.h>
00047 #include <phy.h>
00048 #include <mrcl_propagation.h>
00049 #include <modulation.h>
00050 #include <omni-antenna.h>
00051 #include <mrcl_wireless-phy.h>
00052 #include <packet.h>
00053 #include <ip.h>
00054 #include <agent.h>
00055 #include <trace.h>
00056 
00057 #include <diffusion/diff_header.h>
00058 
00059 #define MAX(a,b) (((a)<(b))?(b):(a))
00060 
00061 #define MIN(a,b) (((a)<(b))?(a):(b))
00062 
00063 void MrclSleep_Timer::expire(Event *) {
00064         a_->UpdateSleepEnergy();
00065 }
00066 
00067 
00068 /* ======================================================================
00069    MrclWirelessPhy Interface
00070    ====================================================================== */
00071 static class MrclWirelessPhyClass: public TclClass {
00072 public:
00073         MrclWirelessPhyClass() : TclClass("Phy/WirelessPhy/Miracle") {}
00074         TclObject* create(int, const char*const*) {
00075                 return (new MrclWirelessPhy);
00076         }
00077 } class_MrclWirelessPhy;
00078 
00079 
00080 MrclWirelessPhy::MrclWirelessPhy() : Phy(), sleep_timer_(this), status_(IDLE)
00081 {
00082         /*
00083          *  It sounds like 10db should be the capture threshold.
00084          *
00085          *  If a node is presently receiving a packet a a power level
00086          *  Pa, and a packet at power level Pb arrives, the following
00087          *  comparion must be made to determine whether or not capture
00088          *  occurs:
00089          *
00090          *    10 * log(Pa) - 10 * log(Pb) > 10db
00091          *
00092          *  OR equivalently
00093          *
00094          *    Pa/Pb > 10.
00095          *
00096          */
00097         bind("CPThresh_", &CPThresh_);
00098         bind("CSThresh_", &CSThresh_);
00099         bind("RXThresh_", &RXThresh_);
00100         //bind("bandwidth_", &bandwidth_);
00101         bind("Pt_", &Pt_);
00102         bind("freq_", &freq_);
00103         bind("L_", &L_);
00104         
00105         lambda_ = SPEED_OF_LIGHT / freq_;
00106 
00107         node_ = 0;
00108         ant_ = 0;
00109         propagation_ = 0;
00110         modulation_ = 0;
00111 
00112         // Assume AT&T's Wavelan PCMCIA card -- Chalermek
00113         //      Pt_ = 8.5872e-4; // For 40m transmission range.
00114         //      Pt_ = 7.214e-3;  // For 100m transmission range.
00115         //      Pt_ = 0.2818; // For 250m transmission range.
00116         //      Pt_ = pow(10, 2.45) * 1e-3;         // 24.5 dbm, ~ 281.8mw
00117         
00118         Pt_consume_ = 0.660;  // 1.6 W drained power for transmission
00119         Pr_consume_ = 0.395;  // 1.2 W drained power for reception
00120 
00121         //      P_idle_ = 0.035; // 1.15 W drained power for idle
00122 
00123         P_idle_ = 0.0;
00124         P_sleep_ = 0.00;
00125         P_transition_ = 0.00;
00126         node_on_=1;
00127         
00128         channel_idle_time_ = NOW;
00129         update_energy_time_ = NOW;
00130         last_send_time_ = NOW;
00131         
00132         sleep_timer_.resched(1.0);
00133 
00134 }
00135 
00136 int
00137 MrclWirelessPhy::command(int argc, const char*const* argv)
00138 {
00139         TclObject *obj; 
00140 
00141         if (argc==2) {
00142                 if (strcasecmp(argv[1], "NodeOn") == 0) {
00143                         node_on();
00144 
00145 //                      if (em() == NULL) 
00146 //                              return TCL_OK;
00147 //                      if (NOW > update_energy_time_) {
00148 //                              update_energy_time_ = NOW;
00149 //                      }
00150                         return TCL_OK;
00151                 } else if (strcasecmp(argv[1], "NodeOff") == 0) {
00152                         node_off();
00153 
00154 //                      if (em() == NULL) 
00155 //                              return TCL_OK;
00156 //                      if (NOW > update_energy_time_) {
00157 //                              em()->DecrIdleEnergy(NOW-update_energy_time_,
00158 //                                                   P_idle_);
00159 //                              update_energy_time_ = NOW;
00160 //                      }
00161                         return TCL_OK;
00162                 }
00163         } else if(argc == 3) {
00164                 if (strcasecmp(argv[1], "setTxPower") == 0) {
00165                         Pt_consume_ = atof(argv[2]);
00166                         return TCL_OK;
00167                 } else if (strcasecmp(argv[1], "setRxPower") == 0) {
00168                         Pr_consume_ = atof(argv[2]);
00169                         return TCL_OK;
00170                 } else if (strcasecmp(argv[1], "setIdlePower") == 0) {
00171                         P_idle_ = atof(argv[2]);
00172                         return TCL_OK;
00173                 }else if (strcasecmp(argv[1], "setSleepPower") == 0) {
00174                         P_sleep_ = atof(argv[2]);
00175                         return TCL_OK;
00176                 } else if (strcasecmp(argv[1], "setTransitionPower") == 0) {
00177                         P_transition_ = atof(argv[2]);
00178                         return TCL_OK;
00179                 } else if (strcasecmp(argv[1], "setTransitionTime") == 0) {
00180                         T_transition_ = atof(argv[2]);
00181                         return TCL_OK;
00182                 }else if( (obj = TclObject::lookup(argv[2])) == 0) {
00183                         fprintf(stderr,"MrclWirelessPhy: %s lookup of %s failed\n", 
00184                                 argv[1], argv[2]);
00185                         return TCL_ERROR;
00186                 }else if (strcmp(argv[1], "propagation") == 0) {
00187                         assert(propagation_ == 0);
00188                         propagation_ = (DeiPropagation*) obj;
00189                         return TCL_OK;
00190                 } else if (strcasecmp(argv[1], "antenna") == 0) {
00191                         ant_ = (Antenna*) obj;
00192                         return TCL_OK;
00193                 } else if (strcasecmp(argv[1], "node") == 0) {
00194                         assert(node_ == 0);
00195                         node_ = (Node *)obj;
00196                         return TCL_OK;
00197                 }
00198         }
00199         return Phy::command(argc,argv);
00200 }
00201  
00202 void 
00203 MrclWirelessPhy::sendDown(Packet *p)
00204 {
00205         /*
00206          * Sanity Check
00207          */
00208         assert(initialized());
00209         
00210 /*      if (em()) {
00211                         //node is off here...
00212                         if (Is_node_on() != true ) {
00213                         Packet::free(p);
00214                         return;
00215                         }
00216                         if(Is_node_on() == true && Is_sleeping() == true){
00217                         em()-> DecrSleepEnergy(NOW-update_energy_time_,
00218                                                         P_sleep_);
00219                         update_energy_time_ = NOW;
00220 
00221                         }
00222 
00223         }*/
00224         /*
00225          * Decrease node's energy
00226          */
00227         if(em()) {
00228                 if (em()->energy() > 0) {
00229 
00230                     double txtime = hdr_cmn::access(p)->txtime();
00231                     double start_time = MAX(channel_idle_time_, NOW);
00232                     double end_time = MAX(channel_idle_time_, NOW+txtime);
00233                     double actual_txtime = end_time-start_time;
00234 
00235                     if (start_time > update_energy_time_) {
00236                             em()->DecrIdleEnergy(start_time - 
00237                                                  update_energy_time_, P_idle_);
00238                             update_energy_time_ = start_time;
00239                     }
00240 
00241                     /* It turns out that MAC sends packet even though, it's
00242                        receiving some packets.
00243                     
00244                     if (txtime-actual_txtime > 0.000001) {
00245                             fprintf(stderr,"Something may be wrong at MAC\n");
00246                             fprintf(stderr,"act_tx = %lf, tx = %lf\n", actual_txtime, txtime);
00247                     }
00248                     */
00249 
00250                    // Sanity check
00251                    double temp = MAX(NOW,last_send_time_);
00252 
00253                    /*
00254                    if (NOW < last_send_time_) {
00255                            fprintf(stderr,"Argggg !! Overlapping transmission. NOW %lf last %lf temp %lf\n", NOW, last_send_time_, temp);
00256                    }
00257                    */
00258                    
00259                    double begin_adjust_time = MIN(channel_idle_time_, temp);
00260                    double finish_adjust_time = MIN(channel_idle_time_, NOW+txtime);
00261                    double gap_adjust_time = finish_adjust_time - begin_adjust_time;
00262                    if (gap_adjust_time < 0.0) {
00263                            fprintf(stderr,"What the heck ! negative gap time.\n");
00264                    }
00265 
00266                    if ((gap_adjust_time > 0.0) && (status_ == RECV)) {
00267                            em()->DecrTxEnergy(gap_adjust_time,
00268                                               Pt_consume_-Pr_consume_);
00269                    }
00270 
00271                    em()->DecrTxEnergy(actual_txtime,Pt_consume_);
00272 //                 if (end_time > channel_idle_time_) {
00273 //                         status_ = SEND;
00274 //                 }
00275 //
00276                    status_ = IDLE;
00277 
00278                    last_send_time_ = NOW+txtime;
00279                    channel_idle_time_ = end_time;
00280                    update_energy_time_ = end_time;
00281 
00282                    if (em()->energy() <= 0) {
00283                            em()->setenergy(0);
00284                            ((MobileNode*)node())->log_energy(0);
00285                    }
00286 
00287                 } else {
00288 
00289                         // log node energy
00290                         if (em()->energy() > 0) {
00291                                 ((MobileNode *)node_)->log_energy(1);
00292                         } 
00293 //
00294                         Packet::free(p);
00295                         return;
00296                 }
00297         }
00298 
00299         /*
00300          *  Stamp the packet with the interface arguments
00301          */
00302         p->txinfo_.stamp((MobileNode*)0, ant_->copy(), Pt_, lambda_);
00303         
00304         // Send the packet
00305         channel_->recv(p, this);
00306 }
00307 
00308 int 
00309 MrclWirelessPhy::sendUp(Packet *p)
00310 {
00311         /*
00312          * Sanity Check
00313          */
00314         assert(initialized());
00315 
00316         PacketStamp s;
00317         double Pr;
00318         int pkt_recvd = 0;
00319 
00320         Pr = p->txinfo_.getTxPr();
00321         
00322         // if the node is in sleeping mode, drop the packet simply
00323         if (em()) {
00324                         if (Is_node_on()!= true){
00325                         pkt_recvd = 0;
00326                         goto DONE;
00327                         }
00328 
00329                         if (Is_sleeping()==true && (Is_node_on() == true)) {
00330                                 pkt_recvd = 0;
00331                                 goto DONE;
00332                         }
00333                         
00334         }
00335         // if the energy goes to ZERO, drop the packet simply
00336         if (em()) {
00337                 if (em()->energy() <= 0) {
00338                         pkt_recvd = 0;
00339                         goto DONE;
00340                 }
00341         }
00342 
00343         if(propagation_) {
00344                 s.stamp((MobileNode*)node(), ant_, 0, lambda_);
00345                 Pr = propagation_->Pr(p,&p->txinfo_, &s, getL(), getLambda());
00346                 if (Pr < CSThresh_) {
00347                         pkt_recvd = 0;
00348                         goto DONE;
00349                 }
00350                 if (Pr < RXThresh_) {
00351                         /*
00352                          * We can detect, but not successfully receive
00353                          * this packet.
00354                          */
00355                         hdr_cmn *hdr = HDR_CMN(p);
00356                         hdr->error() = 1;
00357 #if DEBUG > 3
00358                         printf("SM %f.9 _%d_ drop pkt from %d low POWER %e/%e\n",
00359                                Scheduler::instance().clock(), node()->index(),
00360                                p->txinfo_.getNode()->index(),
00361                                Pr,RXThresh);
00362 #endif
00363                 }
00364         }
00365         if(modulation_) {
00366                 hdr_cmn *hdr = HDR_CMN(p);
00367                 hdr->error() = modulation_->BitError(Pr);
00368         }
00369         
00370         /*
00371          * The MAC layer must be notified of the packet reception
00372          * now - ie; when the first bit has been detected - so that
00373          * it can properly do Collision Avoidance / Detection.
00374          */
00375         pkt_recvd = 1;
00376 
00377 DONE:
00378         p->txinfo_.getAntenna()->release();
00379 
00380         /* WILD HACK: The following two variables are a wild hack.
00381            They will go away in the next release...
00382            They're used by the mac-802_11 object to determine
00383            capture.  This will be moved into the net-if family of 
00384            objects in the future. */
00385         p->txinfo_.RxPr = Pr;
00386         p->txinfo_.CPThresh = CPThresh_;
00387 
00388         /*
00389          * Decrease energy if packet successfully received
00390          */
00391         if(pkt_recvd && em()) {
00392 
00393                 double rcvtime = hdr_cmn::access(p)->txtime();
00394                 // no way to reach here if the energy level < 0
00395                 
00396                 double start_time = MAX(channel_idle_time_, NOW);
00397                 double end_time = MAX(channel_idle_time_, NOW+rcvtime);
00398                 double actual_rcvtime = end_time-start_time;
00399 
00400                 if (start_time > update_energy_time_) {
00401                         em()->DecrIdleEnergy(start_time-update_energy_time_,
00402                                              P_idle_);
00403                         update_energy_time_ = start_time;
00404                 }
00405                 
00406                 em()->DecrRcvEnergy(actual_rcvtime,Pr_consume_);
00407 /*
00408   if (end_time > channel_idle_time_) {
00409   status_ = RECV;
00410   }
00411 */
00412                 channel_idle_time_ = end_time;
00413                 update_energy_time_ = end_time;
00414 
00415                 status_ = IDLE;
00416 
00417                 /*
00418                   hdr_diff *dfh = HDR_DIFF(p);
00419                   printf("Node %d receives (%d, %d, %d) energy %lf.\n",
00420                   node()->address(), dfh->sender_id.addr_, 
00421                   dfh->sender_id.port_, dfh->pk_num, node()->energy());
00422                 */
00423 
00424                 // log node energy
00425                 if (em()->energy() > 0) {
00426                 ((MobileNode *)node_)->log_energy(1);
00427                 } 
00428 
00429                 if (em()->energy() <= 0) {  
00430                         // saying node died
00431                         em()->setenergy(0);
00432                         ((MobileNode*)node())->log_energy(0);
00433                 }
00434         }
00435         
00436         return pkt_recvd;
00437 }
00438 
00439 void
00440 MrclWirelessPhy::node_on()
00441 {
00442 
00443         node_on_= TRUE;
00444         status_ = IDLE;
00445 
00446        if (em() == NULL)
00447             return;     
00448         if (NOW > update_energy_time_) {
00449             update_energy_time_ = NOW;
00450         }
00451 }
00452 
00453 void 
00454 MrclWirelessPhy::node_off()
00455 {
00456 
00457         node_on_= FALSE;
00458         status_ = SLEEP;
00459 
00460         if (em() == NULL)
00461             return;
00462         if (NOW > update_energy_time_) {
00463             em()->DecrIdleEnergy(NOW-update_energy_time_,
00464                                 P_idle_);
00465             update_energy_time_ = NOW;
00466         }
00467 }
00468 
00469 void 
00470 MrclWirelessPhy::node_wakeup()
00471 {
00472 
00473         if (status_== IDLE)
00474                 return;
00475 
00476         if (em() == NULL)
00477             return;
00478 
00479         if ( NOW > update_energy_time_ && (status_== SLEEP) ) {
00480                 //the power consumption when radio goes from SLEEP mode to IDLE mode
00481                 em()->DecrTransitionEnergy(T_transition_,P_transition_);
00482                 
00483                 em()->DecrSleepEnergy(NOW-update_energy_time_,
00484                                       P_sleep_);
00485                 status_ = IDLE;
00486                 update_energy_time_ = NOW;
00487                 
00488                 // log node energy
00489                 if (em()->energy() > 0) {
00490                         ((MobileNode *)node_)->log_energy(1);
00491                 } else {
00492                         ((MobileNode *)node_)->log_energy(0);   
00493                 }
00494         }
00495 }
00496 
00497 void 
00498 MrclWirelessPhy::node_sleep()
00499 {
00500 //
00501 //        node_on_= FALSE;
00502 //
00503         if (status_== SLEEP)
00504                 return;
00505 
00506         if (em() == NULL)
00507             return;
00508 
00509         if ( NOW > update_energy_time_ && (status_== IDLE) ) {
00510         //the power consumption when radio goes from IDLE mode to SLEEP mode
00511             em()->DecrTransitionEnergy(T_transition_,P_transition_);
00512 
00513             em()->DecrIdleEnergy(NOW-update_energy_time_,
00514                                 P_idle_);
00515                 status_ = SLEEP;
00516                 update_energy_time_ = NOW;
00517 
00518         // log node energy
00519                 if (em()->energy() > 0) {
00520                         ((MobileNode *)node_)->log_energy(1);
00521                 } else {
00522                         ((MobileNode *)node_)->log_energy(0);   
00523                 }
00524         }
00525 }
00526 //
00527 void
00528 MrclWirelessPhy::dump(void) const
00529 {
00530         Phy::dump();
00531         fprintf(stdout,
00532                 "\tPt: %f, Gt: %f, Gr: %f, lambda: %f, L: %f\n",
00533                 Pt_, ant_->getTxGain(0,0,0,lambda_), ant_->getRxGain(0,0,0,lambda_), lambda_, L_);
00534         //fprintf(stdout, "\tbandwidth: %f\n", bandwidth_);
00535         fprintf(stdout, "--------------------------------------------------\n");
00536 }
00537 
00538 
00539 void MrclWirelessPhy::UpdateIdleEnergy()
00540 {
00541         if (em() == NULL) {
00542                 return;
00543         }
00544         if (NOW > update_energy_time_ && (Is_node_on()==TRUE && status_ == IDLE ) ) {
00545                   em()-> DecrIdleEnergy(NOW-update_energy_time_,
00546                                         P_idle_);
00547                   update_energy_time_ = NOW;
00548         }
00549 
00550         // log node energy
00551         if (em()->energy() > 0) {
00552                 ((MobileNode *)node_)->log_energy(1);
00553         } else {
00554                 ((MobileNode *)node_)->log_energy(0);   
00555         }
00556 
00557 //      idle_timer_.resched(10.0);
00558 }
00559 
00560 double MrclWirelessPhy::getDist(double Pr, double Pt, double Gt, double Gr,
00561                             double hr, double ht, double L, double lambda)
00562 {
00563         if (propagation_) {
00564                 return propagation_->getDist(Pr, Pt, Gt, Gr, hr, ht, L,
00565                                              lambda);
00566         }
00567         return 0;
00568 }
00569 
00570 //
00571 void MrclWirelessPhy::UpdateSleepEnergy()
00572 {
00573         if (em() == NULL) {
00574                 return;
00575         }
00576         if (NOW > update_energy_time_ && ( Is_node_on()==TRUE  && Is_sleeping() == true) ) {
00577                   em()-> DecrSleepEnergy(NOW-update_energy_time_,
00578                                         P_sleep_);
00579                   update_energy_time_ = NOW;
00580                 // log node energy
00581                 if (em()->energy() > 0) {
00582                         ((MobileNode *)node_)->log_energy(1);
00583                 } else {
00584                         ((MobileNode *)node_)->log_energy(0);   
00585                 }
00586         }
00587         
00588         //A hack to make states consistent with those of in Energy Model for AF
00589         int static s=em()->sleep();
00590         if(em()->sleep()!=s){
00591 
00592                 s=em()->sleep();        
00593                 if(s==1)
00594                         node_sleep();
00595                 else
00596                         node_wakeup();                  
00597                 printf("\n AF hack %d\n",em()->sleep());        
00598         }       
00599         
00600         sleep_timer_.resched(10.0);
00601 }

Generated on Wed Nov 26 15:47:28 2008 for NS-MIRACLE library by  doxygen 1.5.2