wireless-phy.cc

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

Generated on Tue Mar 6 16:47:53 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6