mphy.cc

00001 /*
00002  * Copyright (c) 2007 Regents of the SIGNET lab, University of Padova.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University of Padova (SIGNET lab) nor the 
00014  *    names of its contributors may be used to endorse or promote products 
00015  *    derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00018  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
00019  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
00020  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
00021  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00022  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00023  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00024  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00025  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00026  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00027  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include<iostream>
00031 #include<module.h>
00032 #include<clmessage.h>
00033 
00034 #include "mphy.h"
00035 #include "phymac-clmsg.h"
00036 #include "clmsg-phy-on-off-switch.h"
00037 
00038 
00039 
00040 
00041 MPhy::MPhy()
00042   : txtimer(this), rxtimer(this),
00043   interference_(0), propagation_(0),
00044   antenna_(0), spectralmask_(0),
00045   correlation_(0), isOn(true)
00046 {
00047   // binding to TCL variables
00048   bind("TxPower_", &TxPower_);
00049   bind("NoiseSPD_", &NoiseSPD_);
00050 }
00051 
00052 MPhy::~MPhy()
00053 {
00054 
00055 }
00056 
00057 int MPhy::command(int argc, const char*const* argv)
00058 {
00059   //printf("MPhy::command -- %s (%d)\n", argv[1], argc);
00060   Tcl& tcl = Tcl::instance();
00061 
00062   if(argc == 2)
00063     {
00064 
00065       if(strcasecmp(argv[1], "getPropagation")==0)
00066         {
00067           if(!propagation_)
00068             return TCL_ERROR;
00069           tcl.result(propagation_->name());
00070           return TCL_OK;
00071         }
00072 
00073       if(strcasecmp(argv[1], "getAntenna")==0)
00074         {
00075           if(!antenna_)
00076             return TCL_ERROR;
00077           tcl.result(antenna_->name());
00078           return TCL_OK;
00079         }
00080 
00081       if(strcasecmp(argv[1], "getSpectralMask")==0)
00082         {
00083 
00084           if(!spectralmask_)
00085             return TCL_ERROR;
00086           tcl.result(spectralmask_->name());
00087           return TCL_OK;
00088         }
00089 
00090       if(strcasecmp(argv[1], "getInterference")==0)
00091         {
00092           if(!interference_)
00093             return TCL_ERROR;
00094           tcl.result(interference_->name());
00095           return TCL_OK;
00096         }
00097 
00098       if(strcasecmp(argv[1], "getCorrelation")==0)
00099         {
00100           if(!correlation_)
00101             return TCL_ERROR;
00102           tcl.result(correlation_->name());
00103           return TCL_OK;
00104         }
00105     }
00106 
00107   if(argc == 3)
00108     {
00109 
00110       if(strcasecmp(argv[1], "setPropagation")==0)
00111         {
00112           // dynamic cast returns NULL if object is not of the correct type
00113           propagation_ = dynamic_cast<MPropagation*> (TclObject::lookup(argv[2]));
00114           if(!propagation_)
00115             return TCL_ERROR;
00116           return TCL_OK;
00117         }
00118 
00119       if(strcasecmp(argv[1], "setAntenna")==0)
00120         {
00121           // dynamic cast returns NULL if object is not of the correct type
00122           antenna_ = dynamic_cast<MAntenna*> (TclObject::lookup(argv[2]));
00123           if(!antenna_)
00124             return TCL_ERROR;
00125           return TCL_OK;
00126         }
00127 
00128       if(strcasecmp(argv[1], "setSpectralMask")==0)
00129         {
00130           // dynamic cast returns NULL if object is not of the correct type
00131           spectralmask_ = dynamic_cast<MSpectralMask*> (TclObject::lookup(argv[2]));
00132           if(!spectralmask_)
00133             return TCL_ERROR;
00134           return TCL_OK;
00135         }
00136 
00137       if(strcasecmp(argv[1], "setInterference")==0)
00138         {
00139           // dynamic cast returns NULL if object is not of the correct type
00140           interference_ = dynamic_cast<MInterference*> (TclObject::lookup(argv[2]));
00141           if(!interference_)
00142             return TCL_ERROR;
00143           return TCL_OK;
00144         }
00145 
00146       if(strcasecmp(argv[1], "setCorrelation")==0)
00147         {
00148           // dynamic cast returns NULL if object is not of the correct type
00149           correlation_ = dynamic_cast<MCorrelation*> (TclObject::lookup(argv[2]));
00150           if(!correlation_)
00151             return TCL_ERROR;
00152           return TCL_OK;
00153         }
00154     }
00155 
00156   return Module::command(argc, argv);
00157 }
00158 
00159 
00160 
00161 /*
00162  * Very naive implementation of modulation type registration
00163  * 
00164  */
00165 
00166 #define MPHY_MAX_MOD_TYPES 200
00167 #define MPHY_MAX_MOD_NAME_LENGTH 10
00168 
00169 static int mphy_mod_id_counter = -1;
00170 
00171 static char mphy_mod_name[MPHY_MAX_MOD_TYPES][MPHY_MAX_MOD_NAME_LENGTH];
00172 
00173 int MPhy::registerModulationType(const char* name)
00174 {
00175 
00176   mphy_mod_id_counter++;
00177   assert( (mphy_mod_id_counter >=0) && (mphy_mod_id_counter < MPHY_MAX_MOD_TYPES));
00178   strncpy(&mphy_mod_name[mphy_mod_id_counter][0], name, MPHY_MAX_MOD_NAME_LENGTH-1);
00179 
00180   // null-terminate to segfaults in case string was truncated
00181   mphy_mod_name[mphy_mod_id_counter][ MPHY_MAX_MOD_NAME_LENGTH-1] = '\0';
00182 
00183   return mphy_mod_id_counter;
00184 }
00185 
00186 const char* MPhy::getModulationName(int id)
00187 {
00188   //  std::cerr << "getModulationName(" << id <<")" << std::endl;
00189   if((id>=0)&&(id<=mphy_mod_id_counter)&&(id<MPHY_MAX_MOD_TYPES))
00190     return (&mphy_mod_name[id][0]);
00191   else
00192     return "UNKNOWN";
00193 }
00194 
00195 
00196 
00197 
00198 
00199 void MPhy::recv(Packet* p)
00200 {
00201 
00202   hdr_cmn *ch = HDR_CMN(p);
00203   hdr_MPhy *ph = HDR_MPHY(p);
00204 
00205   if(ch->direction() == hdr_cmn::UP)
00206     {
00207       ph->dstSpectralMask = getRxSpectralMask(p); 
00208       ph->dstPosition = getPosition();
00209       ph->dstAntenna = getRxAntenna(p);
00210 
00211       assert(ph->dstSpectralMask);
00212       assert(ph->dstPosition);   
00213 
00214       ph->Pr = getRxPower(p); 
00215 
00216       // The following is to avoid some floating point exceptions when using
00217       // uninitialized values which happen to be NAN or INF. This is
00218       // due to the following facts:
00219       // 1) txinfo.RxPr and txinfo.CPThresh are manually copied in Module::copy(Packet*) to
00220       //    support some possible (though unlikely) case in which you
00221       //    need to preserve these values throughout a packet copy
00222       // 2) neither RxPr nor CPThresh are initialized upon packet
00223       //    creation, they are just assigned by old ns2 wireless-phy, so
00224       //    if you're not using wireless-phy they are almost random 
00225       // To fix this issue, we're setting the values to 0 since we're
00226       // not using them. 
00227       p->txinfo_.RxPr = 0;
00228       p->txinfo_.CPThresh = 0;
00229 
00230       /* To reduce complexity, if the received power for this
00231        * transmission is zero, we completely neglect this packet.
00232        */
00233       if (ph->Pr > 0)  
00234         {         
00235           ph->Pn = getNoisePower(p);
00236 
00237           if (interference_) 
00238             {   
00239               interference_->addToInterference(p);
00240             }
00241 
00242           ph->rxtime = NOW;
00243           ph->worth_tracing = true;
00244  
00245           // new control: interrupt must be on and no tx must be pending
00246           if (isOn == true) {
00247              PacketEvent* pe = new PacketEvent(p);
00248              Scheduler::instance().schedule(&rxtimer, pe, ph->duration);
00249           
00250              startRx(p);
00251           }
00252           else {
00253              // phy is OFF, we must free the packet
00254              Packet::free(p);
00255            }
00256         }
00257       else
00258         {        
00259           Packet::free(p);
00260         }
00261 
00262 
00263     }    
00264   else // Direction DOWN
00265     {
00266  
00267       // new control: phy must be ON.
00268       assert(isOn);
00269       
00270       // we would like to copy the TxSpectralMask and TxAntenna so
00271       // that we are sure that their parameters are not changed when
00272       // the packet is received. Unfortunately, we cannot do that:
00273       // 1) the object would not get deleted when p is deleted
00274       // 2) the object would not get copied when p->copy() is called,
00275       //    so we would have just 1 copy per packet transmitted
00276       // 3) having just a single copy, we cannot detect at the receiver
00277       //    when the last packet gets deleted so to also delete the
00278       //    spectral mask/antenna
00279       // So we have to stick to pointers to instances which the PHY will keep
00280       // allocated for all the necessary time.
00281 
00282       ph->Pr = 0;
00283       ph->Pn = 0;
00284       ph->Pi = 0;
00285       ph->txtime = NOW;
00286       ph->rxtime = ph->txtime; // so that incomplete tracing can occur
00287 
00288       ph->worth_tracing = false;
00289 
00290       ph->srcSpectralMask =  getTxSpectralMask(p);
00291       ph->srcAntenna = getTxAntenna(p);
00292       ph->srcPosition = getPosition();
00293       ph->dstSpectralMask = 0;
00294       ph->dstPosition = 0;      
00295       ph->dstAntenna = 0;
00296       ph->modulationType = getModulationType(p);
00297       ph->duration = getTxDuration(p);
00298 
00299       ph->Pt = getTxPower(p);
00300 
00301       assert(ph->srcSpectralMask);
00302       assert(ph->srcPosition);      
00303       assert(ph->duration > 0);
00304       assert(ph->Pt > 0);
00305 
00306       // we copy the packet so that we are sure that the reference
00307       // passed to the Packet Event is valid 
00308       PacketEvent* pe = new PacketEvent(p->copy());
00309       Scheduler::instance().schedule(&txtimer, pe, ph->duration);
00310 
00311       startTx(p);
00312 
00313     }
00314 
00315 }
00316 
00318  
00319 int MPhy::recvSyncClMsg(ClMessage* m)
00320 {
00321 
00322   if (m->type() == CLMSG_MAC2PHY_GETTXDURATION)
00323     {
00324 
00325       Packet* pkt = ((ClMsgMac2PhyGetTxDuration*)m)->pkt;
00326 
00327       hdr_MPhy* ph = HDR_MPHY(pkt);
00328 
00329       ph->srcSpectralMask = getTxSpectralMask(pkt);
00330 
00331       double duration = getTxDuration(pkt);
00332 
00333       ((ClMsgMac2PhyGetTxDuration*)m)->setDuration(duration);
00334       return 0;
00335     }
00336   else if (m->type() == CLMSG_PHY_ON_OFF_SWITCH) {
00337       if ( ((ClMsgPhyOnOffSwitch*)m)->isOn() == true) turnOn();
00338       else turnOff();
00339       return 0;
00340   }
00341   else if (m->type() == CLMSG_PHY_ON_OFF_SWITCH_STATUS) {
00342       ((ClMsgPhyOnOffSwitchStatus*)m)->setStatus(isOn);
00343       return 0;
00344   }
00345   else return Module::recvSyncClMsg(m);
00346 }
00347 
00348 double MPhy::getRxPower(Packet* p)
00349 {
00350   hdr_MPhy *ph = HDR_MPHY(p);
00351 
00352   double tag=1; // TX Antenna gain
00353   double rag=1; // RX Antenna gain
00354   double pg=1;  // Propagation Gain
00355   double smg=1; // Spectral Mask Gain
00356   double cg=1;  // Correlation Gain
00357 
00358 
00359   assert(ph->srcSpectralMask && ph->dstSpectralMask);
00360 
00361   smg = ph->srcSpectralMask->getOverlap(ph->dstSpectralMask, p);    
00362   if (smg == 0) return 0;
00363 
00364 
00365   if (ph->srcAntenna)     
00366       tag = ph->srcAntenna->getGain(p);
00367 
00368   if (tag == 0) return 0;
00369 
00370 
00371   if (ph->dstAntenna)
00372     rag = ph->dstAntenna->getGain(p);
00373 
00374   if (rag == 0) return 0;
00375 
00376   if (propagation_) 
00377       pg = propagation_->getGain(p);
00378 
00379   if (pg == 0) return 0;
00380 
00381   if (correlation_)
00382     cg = correlation_->getGain(p);
00383 
00384   double Pr =  (ph->Pt * smg * tag * rag * pg * cg);
00385 
00386   if (debug_)    std::cerr << NOW 
00387                            << " Pt=" << ph->Pt
00388                            << " SMG=" << smg
00389                            << " TAG=" << tag
00390                            << " RAG=" << rag
00391                            << " PG=" << pg
00392                            << " CG=" << cg
00393                            << " Pr=" << Pr
00394                            << " duration=" << ph->duration
00395                            << std::endl;
00396   
00397   return Pr;
00398 }
00399 
00400 
00401 
00402 double MPhy::getNoisePower(Packet* p) 
00403 {
00404   MSpectralMask* sm= getRxSpectralMask(p);
00405   assert(sm);
00406   return (NoiseSPD_ * sm->getBandwidth());
00407 }
00408 
00409 
00410 
00411 void MPhyRxTimer::handle(Event* e)
00412 {
00413   PacketEvent* pe = (PacketEvent*) e;
00414   assert(pe);
00415   Packet* p = pe->pkt;
00416   assert(p);
00417   delete e;
00418 
00419   hdr_MPhy *ph = HDR_MPHY(p);
00420 
00421   if (phy->interference_) 
00422     {   
00423       ph->Pi =  phy->interference_->getInterferencePower(p);
00424     }
00425   else
00426     {
00427       ph->Pi = 0;
00428     }
00429 
00430   phy->endRx(p);
00431 
00432 }
00433 
00434 
00435 
00436 
00437 void MPhyTxTimer::handle(Event* e)
00438 {
00439   PacketEvent* pe = (PacketEvent*) e;
00440   assert(pe);
00441   Packet* p = pe->pkt;
00442   assert(p);
00443   delete e;
00444 
00445   phy->endTx(p);
00446 
00447   // we can now delete the copy we made explicitly for this purpose
00448   Packet::free(p);
00449 }
00450 
00451 
00452 
00453 void MPhy::Phy2MacEndTx(const Packet* p)
00454 {
00455   ClMsgPhy2MacEndTx m(p);
00456   sendSyncClMsgUp(&m);
00457 }
00458 
00459 
00460 void MPhy::Phy2MacStartRx(const Packet* p)
00461 {
00462   ClMsgPhy2MacStartRx m(p);
00463   sendSyncClMsgUp(&m);
00464 }
00465 
00466 
00467 
00468 void MPhy::Phy2MacCCA(bool cca)
00469 {
00470   ClMsgPhy2MacCCA m(cca);
00471   sendSyncClMsgUp(&m);
00472 }
00473 

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