wireless-phy.cc
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:15k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- 
  2.  *
  3.  * Copyright (c) 1996 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms, with or without
  7.  * modification, are permitted provided that the following conditions
  8.  * are met:
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer.
  11.  * 2. Redistributions in binary form must reproduce the above copyright
  12.  *    notice, this list of conditions and the following disclaimer in the
  13.  *    documentation and/or other materials provided with the distribution.
  14.  * 3. All advertising materials mentioning features or use of this software
  15.  *    must display the following acknowledgement:
  16.  * This product includes software developed by the Computer Systems
  17.  * Engineering Group at Lawrence Berkeley Laboratory and the Daedalus
  18.  * research group at UC Berkeley.
  19.  * 4. Neither the name of the University nor of the Laboratory may be used
  20.  *    to endorse or promote products derived from this software without
  21.  *    specific prior written permission.
  22.  *
  23.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  24.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  29.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  30.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  32.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  33.  * SUCH DAMAGE.
  34.  *
  35.  * $Header: /cvsroot/nsnam/ns-2/mac/wireless-phy.cc,v 1.28 2007/09/04 04:32:18 tom_henderson Exp $
  36.  *
  37.  * Ported from CMU/Monarch's code, nov'98 -Padma Haldar.
  38.  * wireless-phy.cc
  39.  */
  40. #include <math.h>
  41. #include <packet.h>
  42. #include <mobilenode.h>
  43. #include <phy.h>
  44. #include <propagation.h>
  45. #include <modulation.h>
  46. #include <omni-antenna.h>
  47. #include <wireless-phy.h>
  48. #include <packet.h>
  49. #include <ip.h>
  50. #include <agent.h>
  51. #include <trace.h>
  52. #include <sys/param.h>  /* for MIN/MAX */
  53. #include "diffusion/diff_header.h"
  54. void Sleep_Timer::expire(Event *) {
  55. a_->UpdateSleepEnergy();
  56. }
  57. /* ======================================================================
  58.    WirelessPhy Interface
  59.    ====================================================================== */
  60. static class WirelessPhyClass: public TclClass {
  61. public:
  62.         WirelessPhyClass() : TclClass("Phy/WirelessPhy") {}
  63.         TclObject* create(int, const char*const*) {
  64.                 return (new WirelessPhy);
  65.         }
  66. } class_WirelessPhy;
  67. WirelessPhy::WirelessPhy() : Phy(), sleep_timer_(this), status_(IDLE)
  68. {
  69. /*
  70.  *  It sounds like 10db should be the capture threshold.
  71.  *
  72.  *  If a node is presently receiving a packet a a power level
  73.  *  Pa, and a packet at power level Pb arrives, the following
  74.  *  comparion must be made to determine whether or not capture
  75.  *  occurs:
  76.  *
  77.  *    10 * log(Pa) - 10 * log(Pb) > 10db
  78.  *
  79.  *  OR equivalently
  80.  *
  81.  *    Pa/Pb > 10.
  82.  *
  83.  */
  84. bind("CPThresh_", &CPThresh_);
  85. bind("CSThresh_", &CSThresh_);
  86. bind("RXThresh_", &RXThresh_);
  87. //bind("bandwidth_", &bandwidth_);
  88. bind("Pt_", &Pt_);
  89. bind("freq_", &freq_);
  90. bind("L_", &L_);
  91. lambda_ = SPEED_OF_LIGHT / freq_;
  92. node_ = 0;
  93. ant_ = 0;
  94. propagation_ = 0;
  95. modulation_ = 0;
  96. // Assume AT&T's Wavelan PCMCIA card -- Chalermek
  97.         // Pt_ = 8.5872e-4; // For 40m transmission range.
  98. //      Pt_ = 7.214e-3;  // For 100m transmission range.
  99. //      Pt_ = 0.2818; // For 250m transmission range.
  100. // Pt_ = pow(10, 2.45) * 1e-3;         // 24.5 dbm, ~ 281.8mw
  101. Pt_consume_ = 0.660;  // 1.6 W drained power for transmission
  102. Pr_consume_ = 0.395;  // 1.2 W drained power for reception
  103. // P_idle_ = 0.035; // 1.15 W drained power for idle
  104. P_idle_ = 0.0;
  105. P_sleep_ = 0.00;
  106. T_sleep_ = 10000;
  107. P_transition_ = 0.00;
  108. T_transition_ = 0.00; // 2.31 change: Was not initialized earlier
  109. node_on_=1;
  110. channel_idle_time_ = NOW;
  111. update_energy_time_ = NOW;
  112. last_send_time_ = NOW;
  113. sleep_timer_.resched(1.0);
  114. }
  115. int
  116. WirelessPhy::command(int argc, const char*const* argv)
  117. {
  118. TclObject *obj; 
  119. if (argc==2) {
  120. if (strcasecmp(argv[1], "NodeOn") == 0) {
  121. node_on();
  122. if (em() == NULL) 
  123. return TCL_OK;
  124. if (NOW > update_energy_time_) {
  125. update_energy_time_ = NOW;
  126. }
  127. return TCL_OK;
  128. } else if (strcasecmp(argv[1], "NodeOff") == 0) {
  129. node_off();
  130. if (em() == NULL) 
  131. return TCL_OK;
  132. if (NOW > update_energy_time_) {
  133. em()->DecrIdleEnergy(NOW-update_energy_time_,
  134.      P_idle_);
  135. update_energy_time_ = NOW;
  136. }
  137. return TCL_OK;
  138. }
  139. } else if(argc == 3) {
  140. if (strcasecmp(argv[1], "setTxPower") == 0) {
  141. Pt_consume_ = atof(argv[2]);
  142. return TCL_OK;
  143. } else if (strcasecmp(argv[1], "setRxPower") == 0) {
  144. Pr_consume_ = atof(argv[2]);
  145. return TCL_OK;
  146. } else if (strcasecmp(argv[1], "setIdlePower") == 0) {
  147. P_idle_ = atof(argv[2]);
  148. return TCL_OK;
  149. }else if (strcasecmp(argv[1], "setSleepPower") == 0) {
  150. P_sleep_ = atof(argv[2]);
  151. return TCL_OK;
  152. }else if (strcasecmp(argv[1], "setSleepTime") == 0) {
  153. T_sleep_ = atof(argv[2]);
  154. return TCL_OK;
  155. } else if (strcasecmp(argv[1], "setTransitionPower") == 0) {
  156. P_transition_ = atof(argv[2]);
  157. return TCL_OK;
  158. } else if (strcasecmp(argv[1], "setTransitionTime") == 0) {
  159. T_transition_ = atof(argv[2]);
  160. return TCL_OK;
  161. }else if( (obj = TclObject::lookup(argv[2])) == 0) {
  162. fprintf(stderr,"WirelessPhy: %s lookup of %s failedn", 
  163. argv[1], argv[2]);
  164. return TCL_ERROR;
  165. }else if (strcmp(argv[1], "propagation") == 0) {
  166. assert(propagation_ == 0);
  167. propagation_ = (Propagation*) obj;
  168. return TCL_OK;
  169. } else if (strcasecmp(argv[1], "antenna") == 0) {
  170. ant_ = (Antenna*) obj;
  171. return TCL_OK;
  172. } else if (strcasecmp(argv[1], "node") == 0) {
  173. assert(node_ == 0);
  174. node_ = (Node *)obj;
  175. return TCL_OK;
  176. }
  177. }
  178. return Phy::command(argc,argv);
  179. }
  180.  
  181. void 
  182. WirelessPhy::sendDown(Packet *p)
  183. {
  184. /*
  185.  * Sanity Check
  186.  */
  187. assert(initialized());
  188. if (em()) {
  189. //node is off here...
  190. if (Is_node_on() != true ) {
  191. Packet::free(p);
  192. return;
  193. }
  194. if(Is_node_on() == true && Is_sleeping() == true){
  195. em()-> DecrSleepEnergy(NOW-update_energy_time_,
  196. P_sleep_);
  197. update_energy_time_ = NOW;
  198. }
  199. }
  200. /*
  201.  * Decrease node's energy
  202.  */
  203. if(em()) {
  204. if (em()->energy() > 0) {
  205.     double txtime = hdr_cmn::access(p)->txtime();
  206.     double start_time = MAX(channel_idle_time_, NOW);
  207.     double end_time = MAX(channel_idle_time_, NOW+txtime);
  208.     double actual_txtime = end_time-start_time;
  209.     if (start_time > update_energy_time_) {
  210.     em()->DecrIdleEnergy(start_time - 
  211.  update_energy_time_, P_idle_);
  212.     update_energy_time_ = start_time;
  213.     }
  214.     /* It turns out that MAC sends packet even though, it's
  215.        receiving some packets.
  216.     
  217.     if (txtime-actual_txtime > 0.000001) {
  218.     fprintf(stderr,"Something may be wrong at MACn");
  219.     fprintf(stderr,"act_tx = %lf, tx = %lfn", actual_txtime, txtime);
  220.     }
  221.     */
  222.    // Sanity check
  223.    double temp = MAX(NOW,last_send_time_);
  224.    /*
  225.    if (NOW < last_send_time_) {
  226.    fprintf(stderr,"Argggg !! Overlapping transmission. NOW %lf last %lf temp %lfn", NOW, last_send_time_, temp);
  227.    }
  228.    */
  229.    
  230.    double begin_adjust_time = MIN(channel_idle_time_, temp);
  231.    double finish_adjust_time = MIN(channel_idle_time_, NOW+txtime);
  232.    double gap_adjust_time = finish_adjust_time - begin_adjust_time;
  233.    if (gap_adjust_time < 0.0) {
  234.    fprintf(stderr,"What the heck ! negative gap time.n");
  235.    }
  236.    if ((gap_adjust_time > 0.0) && (status_ == RECV)) {
  237.    em()->DecrTxEnergy(gap_adjust_time,
  238.       Pt_consume_-Pr_consume_);
  239.    }
  240.    em()->DecrTxEnergy(actual_txtime,Pt_consume_);
  241. //    if (end_time > channel_idle_time_) {
  242. //    status_ = SEND;
  243. //    }
  244. //
  245.    status_ = IDLE;
  246.    last_send_time_ = NOW+txtime;
  247.    channel_idle_time_ = end_time;
  248.    update_energy_time_ = end_time;
  249.    if (em()->energy() <= 0) {
  250.    em()->setenergy(0);
  251.    ((MobileNode*)node())->log_energy(0);
  252.    }
  253. } else {
  254. // log node energy
  255. if (em()->energy() > 0) {
  256. ((MobileNode *)node_)->log_energy(1);
  257. //
  258. Packet::free(p);
  259. return;
  260. }
  261. }
  262. /*
  263.  *  Stamp the packet with the interface arguments
  264.  */
  265. p->txinfo_.stamp((MobileNode*)node(), ant_->copy(), Pt_, lambda_);
  266. // Send the packet
  267. channel_->recv(p, this);
  268. }
  269. int 
  270. WirelessPhy::sendUp(Packet *p)
  271. {
  272. /*
  273.  * Sanity Check
  274.  */
  275. assert(initialized());
  276. PacketStamp s;
  277. double Pr;
  278. int pkt_recvd = 0;
  279. Pr = p->txinfo_.getTxPr();
  280. // if the node is in sleeping mode, drop the packet simply
  281. if (em()) {
  282. if (Is_node_on()!= true){
  283. pkt_recvd = 0;
  284. goto DONE;
  285. }
  286. if (Is_sleeping()==true && (Is_node_on() == true)) {
  287. pkt_recvd = 0;
  288. goto DONE;
  289. }
  290. }
  291. // if the energy goes to ZERO, drop the packet simply
  292. if (em()) {
  293. if (em()->energy() <= 0) {
  294. pkt_recvd = 0;
  295. goto DONE;
  296. }
  297. }
  298. if(propagation_) {
  299. s.stamp((MobileNode*)node(), ant_, 0, lambda_);
  300. Pr = propagation_->Pr(&p->txinfo_, &s, this);
  301. if (Pr < CSThresh_) {
  302. pkt_recvd = 0;
  303. goto DONE;
  304. }
  305. if (Pr < RXThresh_) {
  306. /*
  307.  * We can detect, but not successfully receive
  308.  * this packet.
  309.  */
  310. hdr_cmn *hdr = HDR_CMN(p);
  311. hdr->error() = 1;
  312. #if DEBUG > 3
  313. printf("SM %f.9 _%d_ drop pkt from %d low POWER %e/%en",
  314.        Scheduler::instance().clock(), node()->index(),
  315.        p->txinfo_.getNode()->index(),
  316.        Pr,RXThresh);
  317. #endif
  318. }
  319. }
  320. if(modulation_) {
  321. hdr_cmn *hdr = HDR_CMN(p);
  322. hdr->error() = modulation_->BitError(Pr);
  323. }
  324. /*
  325.  * The MAC layer must be notified of the packet reception
  326.  * now - ie; when the first bit has been detected - so that
  327.  * it can properly do Collision Avoidance / Detection.
  328.  */
  329. pkt_recvd = 1;
  330. DONE:
  331. p->txinfo_.getAntenna()->release();
  332. /* WILD HACK: The following two variables are a wild hack.
  333.    They will go away in the next release...
  334.    They're used by the mac-802_11 object to determine
  335.    capture.  This will be moved into the net-if family of 
  336.    objects in the future. */
  337. p->txinfo_.RxPr = Pr;
  338. p->txinfo_.CPThresh = CPThresh_;
  339. /*
  340.  * Decrease energy if packet successfully received
  341.  */
  342. if(pkt_recvd && em()) {
  343. double rcvtime = hdr_cmn::access(p)->txtime();
  344. // no way to reach here if the energy level < 0
  345. double start_time = MAX(channel_idle_time_, NOW);
  346. double end_time = MAX(channel_idle_time_, NOW+rcvtime);
  347. double actual_rcvtime = end_time-start_time;
  348. if (start_time > update_energy_time_) {
  349. em()->DecrIdleEnergy(start_time-update_energy_time_,
  350.      P_idle_);
  351. update_energy_time_ = start_time;
  352. }
  353. em()->DecrRcvEnergy(actual_rcvtime,Pr_consume_);
  354. /*
  355.   if (end_time > channel_idle_time_) {
  356.   status_ = RECV;
  357.   }
  358. */
  359. channel_idle_time_ = end_time;
  360. update_energy_time_ = end_time;
  361. status_ = IDLE;
  362. /*
  363.   hdr_diff *dfh = HDR_DIFF(p);
  364.   printf("Node %d receives (%d, %d, %d) energy %lf.n",
  365.   node()->address(), dfh->sender_id.addr_, 
  366.   dfh->sender_id.port_, dfh->pk_num, node()->energy());
  367. */
  368. // log node energy
  369. if (em()->energy() > 0) {
  370. ((MobileNode *)node_)->log_energy(1);
  371.          } 
  372. if (em()->energy() <= 0) {  
  373. // saying node died
  374. em()->setenergy(0);
  375. ((MobileNode*)node())->log_energy(0);
  376. }
  377. }
  378. return pkt_recvd;
  379. }
  380. void
  381. WirelessPhy::node_on()
  382. {
  383.         node_on_= TRUE;
  384. status_ = IDLE;
  385.        if (em() == NULL)
  386.       return;
  387.     if (NOW > update_energy_time_) {
  388.            update_energy_time_ = NOW;
  389.     }
  390. }
  391. void 
  392. WirelessPhy::node_off()
  393. {
  394.         node_on_= FALSE;
  395. status_ = SLEEP;
  396. if (em() == NULL)
  397.             return;
  398.         if (NOW > update_energy_time_) {
  399.             em()->DecrIdleEnergy(NOW-update_energy_time_,
  400.                                 P_idle_);
  401.             update_energy_time_ = NOW;
  402. }
  403. }
  404. void 
  405. WirelessPhy::node_wakeup()
  406. {
  407. if (status_== IDLE)
  408. return;
  409. if (em() == NULL)
  410.             return;
  411.         if ( NOW > update_energy_time_ && (status_== SLEEP) ) {
  412. //the power consumption when radio goes from SLEEP mode to IDLE mode
  413. em()->DecrTransitionEnergy(T_transition_,P_transition_);
  414. em()->DecrSleepEnergy(NOW-update_energy_time_,
  415.       P_sleep_);
  416. status_ = IDLE;
  417.         update_energy_time_ = NOW;
  418. // log node energy
  419. if (em()->energy() > 0) {
  420. ((MobileNode *)node_)->log_energy(1);
  421.         } else {
  422. ((MobileNode *)node_)->log_energy(0);   
  423.         }
  424. }
  425. }
  426. void 
  427. WirelessPhy::node_sleep()
  428. {
  429. //
  430. //        node_on_= FALSE;
  431. //
  432. if (status_== SLEEP)
  433. return;
  434. if (em() == NULL)
  435.             return;
  436.         if ( NOW > update_energy_time_ && (status_== IDLE) ) {
  437. //the power consumption when radio goes from IDLE mode to SLEEP mode
  438.     em()->DecrTransitionEnergy(T_transition_,P_transition_);
  439.             em()->DecrIdleEnergy(NOW-update_energy_time_,
  440.                                 P_idle_);
  441. status_ = SLEEP;
  442.         update_energy_time_ = NOW;
  443. // log node energy
  444. if (em()->energy() > 0) {
  445. ((MobileNode *)node_)->log_energy(1);
  446.         } else {
  447. ((MobileNode *)node_)->log_energy(0);   
  448.         }
  449. }
  450. }
  451. //
  452. void
  453. WirelessPhy::dump(void) const
  454. {
  455. Phy::dump();
  456. fprintf(stdout,
  457. "tPt: %f, Gt: %f, Gr: %f, lambda: %f, L: %fn",
  458. Pt_, ant_->getTxGain(0,0,0,lambda_), ant_->getRxGain(0,0,0,lambda_), lambda_, L_);
  459. //fprintf(stdout, "tbandwidth: %fn", bandwidth_);
  460. fprintf(stdout, "--------------------------------------------------n");
  461. }
  462. void WirelessPhy::UpdateIdleEnergy()
  463. {
  464. if (em() == NULL) {
  465. return;
  466. }
  467. if (NOW > update_energy_time_ && (Is_node_on()==TRUE && status_ == IDLE ) ) {
  468.   em()-> DecrIdleEnergy(NOW-update_energy_time_,
  469. P_idle_);
  470.   update_energy_time_ = NOW;
  471. }
  472. // log node energy
  473. if (em()->energy() > 0) {
  474. ((MobileNode *)node_)->log_energy(1);
  475.         } else {
  476. ((MobileNode *)node_)->log_energy(0);   
  477.         }
  478. // idle_timer_.resched(10.0);
  479. }
  480. double WirelessPhy::getDist(double Pr, double Pt, double Gt, double Gr,
  481.     double hr, double ht, double L, double lambda)
  482. {
  483. if (propagation_) {
  484. return propagation_->getDist(Pr, Pt, Gt, Gr, hr, ht, L,
  485.      lambda);
  486. }
  487. return 0;
  488. }
  489. //
  490. void WirelessPhy::UpdateSleepEnergy()
  491. {
  492. if (em() == NULL) {
  493. return;
  494. }
  495. if (NOW > update_energy_time_ && ( Is_node_on()==TRUE  && Is_sleeping() == true) ) {
  496.   em()-> DecrSleepEnergy(NOW-update_energy_time_,
  497. P_sleep_);
  498.   update_energy_time_ = NOW;
  499. // log node energy
  500. if (em()->energy() > 0) {
  501. ((MobileNode *)node_)->log_energy(1);
  502.          } else {
  503. ((MobileNode *)node_)->log_energy(0);   
  504.          }
  505. }
  506. //A hack to make states consistent with those of in Energy Model for AF
  507. int static s=em()->sleep();
  508. if(em()->sleep()!=s){
  509. s=em()->sleep();
  510. if(s==1)
  511. node_sleep();
  512. else
  513. node_wakeup();
  514. // printf("n AF hack %dn",em()->sleep());
  515. }
  516. sleep_timer_.resched(10.0);
  517. }