Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

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.19 2002/12/11 01:22:52 difa 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 Idle_Timer::expire(Event *) {
00061         a_->UpdateIdleEnergy();
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(), idle_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 
00122         channel_idle_time_ = NOW;
00123         update_energy_time_ = NOW;
00124         last_send_time_ = NOW;
00125         
00126         idle_timer_.resched(1.0);
00127 }
00128 
00129 int
00130 WirelessPhy::command(int argc, const char*const* argv)
00131 {
00132         TclObject *obj; 
00133 
00134         if (argc==2) {
00135                 if (strcasecmp(argv[1], "NodeOn") == 0) {
00136                         if (em() == NULL) 
00137                                 return TCL_OK;
00138                         if (NOW > update_energy_time_) {
00139                                 update_energy_time_ = NOW;
00140                         }
00141                         return TCL_OK;
00142                 } else if (strcasecmp(argv[1], "NodeOff") == 0) {
00143                         if (em() == NULL) 
00144                                 return TCL_OK;
00145                         if (NOW > update_energy_time_) {
00146                                 em()->DecrIdleEnergy(NOW-update_energy_time_,
00147                                                      P_idle_);
00148                                 update_energy_time_ = NOW;
00149                         }
00150                         return TCL_OK;
00151                 }
00152         } else if(argc == 3) {
00153                 if (strcasecmp(argv[1], "setTxPower") == 0) {
00154                         Pt_consume_ = atof(argv[2]);
00155                         return TCL_OK;
00156                 } else if (strcasecmp(argv[1], "setRxPower") == 0) {
00157                         Pr_consume_ = atof(argv[2]);
00158                         return TCL_OK;
00159                 } else if (strcasecmp(argv[1], "setIdlePower") == 0) {
00160                         P_idle_ = atof(argv[2]);
00161                         return TCL_OK;
00162                 } else if( (obj = TclObject::lookup(argv[2])) == 0) {
00163                         fprintf(stderr,"WirelessPhy: %s lookup of %s failed\n", 
00164                                 argv[1], argv[2]);
00165                         return TCL_ERROR;
00166                 } else if (strcmp(argv[1], "propagation") == 0) {
00167                         assert(propagation_ == 0);
00168                         propagation_ = (Propagation*) obj;
00169                         return TCL_OK;
00170                 } else if (strcasecmp(argv[1], "antenna") == 0) {
00171                         ant_ = (Antenna*) obj;
00172                         return TCL_OK;
00173                 } else if (strcasecmp(argv[1], "node") == 0) {
00174                         assert(node_ == 0);
00175                         node_ = (Node *)obj;
00176                         return TCL_OK;
00177                 }
00178         }
00179         return Phy::command(argc,argv);
00180 }
00181  
00182 void 
00183 WirelessPhy::sendDown(Packet *p)
00184 {
00185         /*
00186          * Sanity Check
00187          */
00188         assert(initialized());
00189         
00190         if (em()) 
00191                 if ((em()->node_on() != true) || (em()->sleep())) {
00192                         Packet::free(p);
00193                         return;
00194                 }
00195 
00196         /*
00197          * Decrease node's energy
00198          */
00199         if(em()) {
00200                 if (em()->energy() > 0) {
00201                         //double txtime = (8.*hdr_cmn::access(p)->size())/bandwidth_;
00202                     double txtime = hdr_cmn::access(p)->txtime();
00203                     double start_time = max(channel_idle_time_, NOW);
00204                     double end_time = max(channel_idle_time_, NOW+txtime);
00205                     double actual_txtime = end_time-start_time;
00206 
00207                     if (start_time > update_energy_time_) {
00208                             em()->DecrIdleEnergy(start_time - 
00209                                                  update_energy_time_, P_idle_);
00210                             update_energy_time_ = start_time;
00211                     }
00212 
00213                     /* It turns out that MAC sends packet even though, it's
00214                        receiving some packets.
00215                     
00216                     if (txtime-actual_txtime > 0.000001) {
00217                             fprintf(stderr,"Something may be wrong at MAC\n");
00218                             fprintf(stderr,"act_tx = %lf, tx = %lf\n", actual_txtime, txtime);
00219                     }
00220                     */
00221 
00222                    // Sanity check
00223                    double temp = max(NOW,last_send_time_);
00224 
00225                    /*
00226                    if (NOW < last_send_time_) {
00227                            fprintf(stderr,"Argggg !! Overlapping transmission. NOW %lf last %lf temp %lf\n", NOW, last_send_time_, temp);
00228                    }
00229                    */
00230                    
00231                    double begin_adjust_time = min(channel_idle_time_, temp);
00232                    double finish_adjust_time = min(channel_idle_time_, NOW+txtime);
00233                    double gap_adjust_time = finish_adjust_time - begin_adjust_time;
00234                    if (gap_adjust_time < 0.0) {
00235                            fprintf(stderr,"What the heck ! negative gap time.\n");
00236                    }
00237 
00238                    if ((gap_adjust_time > 0.0) && (status_ == RECV)) {
00239                            em()->DecrTxEnergy(gap_adjust_time,
00240                                               Pt_consume_-Pr_consume_);
00241                    }
00242 
00243                    em()->DecrTxEnergy(actual_txtime,Pt_consume_);
00244                    if (end_time > channel_idle_time_) {
00245                            status_ = SEND;
00246                    }
00247                                                         
00248                    last_send_time_ = NOW+txtime;
00249                    channel_idle_time_ = end_time;
00250                    update_energy_time_ = end_time;
00251 
00252                    if (em()->energy() <= 0) {
00253                            em()->setenergy(0);
00254                            ((MobileNode*)node())->log_energy(0);
00255                    }
00256 
00257                 } else {
00258                         Packet::free(p);
00259                         return;
00260                 }
00261         }
00262 
00263         /*
00264          *  Stamp the packet with the interface arguments
00265          */
00266         p->txinfo_.stamp((MobileNode*)node(), ant_->copy(), Pt_, lambda_);
00267 
00268         // Send the packet
00269         channel_->recv(p, this);
00270 }
00271 
00272 int 
00273 WirelessPhy::sendUp(Packet *p)
00274 {
00275         /*
00276          * Sanity Check
00277          */
00278         assert(initialized());
00279 
00280         PacketStamp s;
00281         double Pr;
00282         int pkt_recvd = 0;
00283         
00284         // if the node is in sleeping mode, drop the packet simply
00285         if (em()) 
00286                 if (em()->sleep() || (em()->node_on() != true)) {
00287                         pkt_recvd = 0;
00288                         goto DONE;
00289                 }
00290         
00291         // if the energy goes to ZERO, drop the packet simply
00292         if (em()) {
00293                 if (em()->energy() <= 0) {
00294                         pkt_recvd = 0;
00295                         goto DONE;
00296                 }
00297         }
00298 
00299         if(propagation_) {
00300                 s.stamp((MobileNode*)node(), ant_, 0, lambda_);
00301                 Pr = propagation_->Pr(&p->txinfo_, &s, this);
00302                 if (Pr < CSThresh_) {
00303                         pkt_recvd = 0;
00304                         goto DONE;
00305                 }
00306                 if (Pr < RXThresh_) {
00307                         /*
00308                          * We can detect, but not successfully receive
00309                          * this packet.
00310                          */
00311                         hdr_cmn *hdr = HDR_CMN(p);
00312                         hdr->error() = 1;
00313 #if DEBUG > 3
00314                         printf("SM %f.9 _%d_ drop pkt from %d low POWER %e/%e\n",
00315                                Scheduler::instance().clock(), node()->index(),
00316                                p->txinfo_.getNode()->index(),
00317                                Pr,RXThresh);
00318 #endif
00319                 }
00320         }
00321         if(modulation_) {
00322                 hdr_cmn *hdr = HDR_CMN(p);
00323                 hdr->error() = modulation_->BitError(Pr);
00324         }
00325         
00326         /*
00327          * The MAC layer must be notified of the packet reception
00328          * now - ie; when the first bit has been detected - so that
00329          * it can properly do Collision Avoidance / Detection.
00330          */
00331         pkt_recvd = 1;
00332 
00333 DONE:
00334         p->txinfo_.getAntenna()->release();
00335 
00336         /* WILD HACK: The following two variables are a wild hack.
00337            They will go away in the next release...
00338            They're used by the mac-802_11 object to determine
00339            capture.  This will be moved into the net-if family of 
00340            objects in the future. */
00341         p->txinfo_.RxPr = Pr;
00342         p->txinfo_.CPThresh = pow(10,CPThresh_/10); /* CPThresh_ is in db */
00343 
00344         /*
00345          * Decrease energy if packet successfully received
00346          */
00347         if(pkt_recvd && em()) {
00348                 //double rcvtime = (8. * hdr_cmn::access(p)->size())/bandwidth_;
00349                 double rcvtime = hdr_cmn::access(p)->txtime();
00350                 // no way to reach here if the energy level < 0
00351                 
00352                 /*
00353                   node()->add_rcvtime(rcvtime);   
00354                   em()->DecrRcvEnergy(rcvtime,Pr_consume_);
00355                 */
00356 
00357                 double start_time = max(channel_idle_time_, NOW);
00358                 double end_time = max(channel_idle_time_, NOW+rcvtime);
00359                 double actual_rcvtime = end_time-start_time;
00360 
00361                 if (start_time > update_energy_time_) {
00362                         em()->DecrIdleEnergy(start_time-update_energy_time_,
00363                                              P_idle_);
00364                         update_energy_time_ = start_time;
00365                 }
00366                 
00367                 em()->DecrRcvEnergy(actual_rcvtime,Pr_consume_);
00368                 if (end_time > channel_idle_time_) {
00369                         status_ = RECV;
00370                 }
00371 
00372                 channel_idle_time_ = end_time;
00373                 update_energy_time_ = end_time;
00374 
00375                 /*
00376                   hdr_diff *dfh = HDR_DIFF(p);
00377                   printf("Node %d receives (%d, %d, %d) energy %lf.\n",
00378                   node()->address(), dfh->sender_id.addr_, 
00379                   dfh->sender_id.port_, dfh->pk_num, node()->energy());
00380                 */
00381                 
00382                 if (em()->energy() <= 0) {  
00383                         // saying node died
00384                         em()->setenergy(0);
00385                         ((MobileNode*)node())->log_energy(0);
00386                 }
00387         }
00388         
00389         return pkt_recvd;
00390 }
00391 
00392 void
00393 WirelessPhy::node_on()
00394 {
00395         if (em() == NULL)
00396             return;     
00397         if (NOW > update_energy_time_) {
00398             update_energy_time_ = NOW;
00399         }
00400 }
00401 
00402 void 
00403 WirelessPhy::node_off()
00404 {
00405         if (em() == NULL)
00406             return;
00407         if (NOW > update_energy_time_) {
00408             em()->DecrIdleEnergy(NOW-update_energy_time_,
00409                                 P_idle_);
00410             update_energy_time_ = NOW;
00411         }
00412 }
00413 
00414 void
00415 WirelessPhy::dump(void) const
00416 {
00417         Phy::dump();
00418         fprintf(stdout,
00419                 "\tPt: %f, Gt: %f, Gr: %f, lambda: %f, L: %f\n",
00420                 Pt_, ant_->getTxGain(0,0,0,lambda_), ant_->getRxGain(0,0,0,lambda_), lambda_, L_);
00421         //fprintf(stdout, "\tbandwidth: %f\n", bandwidth_);
00422         fprintf(stdout, "--------------------------------------------------\n");
00423 }
00424 
00425 
00426 void WirelessPhy::UpdateIdleEnergy()
00427 {
00428         if (em() == NULL) {
00429                 return;
00430         }
00431         if (NOW > update_energy_time_ && em()->node_on()) {
00432                   em()-> DecrIdleEnergy(NOW-update_energy_time_,
00433                                         P_idle_);
00434                   update_energy_time_ = NOW;
00435         }
00436 
00437         // log node energy
00438         if (em()->energy() > 0) {
00439                 ((MobileNode *)node_)->log_energy(1);
00440         } else {
00441                 ((MobileNode *)node_)->log_energy(0);   
00442         }
00443 
00444         idle_timer_.resched(10.0);
00445 }

Generated on Tue Apr 20 12:14:38 2004 for NS2.26SourcesOriginal by doxygen 1.3.3