00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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
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
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 bind("CPThresh_", &CPThresh_);
00098 bind("CSThresh_", &CSThresh_);
00099 bind("RXThresh_", &RXThresh_);
00100
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
00113
00114
00115
00116
00117
00118 Pt_consume_ = 0.660;
00119 Pr_consume_ = 0.395;
00120
00121
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
00146
00147
00148
00149
00150 return TCL_OK;
00151 } else if (strcasecmp(argv[1], "NodeOff") == 0) {
00152 node_off();
00153
00154
00155
00156
00157
00158
00159
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
00207
00208 assert(initialized());
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
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
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 double temp = MAX(NOW,last_send_time_);
00252
00253
00254
00255
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
00273
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
00290 if (em()->energy() > 0) {
00291 ((MobileNode *)node_)->log_energy(1);
00292 }
00293
00294 Packet::free(p);
00295 return;
00296 }
00297 }
00298
00299
00300
00301
00302 p->txinfo_.stamp((MobileNode*)0, ant_->copy(), Pt_, lambda_);
00303
00304
00305 channel_->recv(p, this);
00306 }
00307
00308 int
00309 MrclWirelessPhy::sendUp(Packet *p)
00310 {
00311
00312
00313
00314 assert(initialized());
00315
00316 PacketStamp s;
00317 double Pr;
00318 int pkt_recvd = 0;
00319
00320 Pr = p->txinfo_.getTxPr();
00321
00322
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
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
00353
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
00372
00373
00374
00375 pkt_recvd = 1;
00376
00377 DONE:
00378 p->txinfo_.getAntenna()->release();
00379
00380
00381
00382
00383
00384
00385 p->txinfo_.RxPr = Pr;
00386 p->txinfo_.CPThresh = CPThresh_;
00387
00388
00389
00390
00391 if(pkt_recvd && em()) {
00392
00393 double rcvtime = hdr_cmn::access(p)->txtime();
00394
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
00409
00410
00411
00412 channel_idle_time_ = end_time;
00413 update_energy_time_ = end_time;
00414
00415 status_ = IDLE;
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 if (em()->energy() > 0) {
00426 ((MobileNode *)node_)->log_energy(1);
00427 }
00428
00429 if (em()->energy() <= 0) {
00430
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
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
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
00502
00503 if (status_== SLEEP)
00504 return;
00505
00506 if (em() == NULL)
00507 return;
00508
00509 if ( NOW > update_energy_time_ && (status_== IDLE) ) {
00510
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
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
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
00551 if (em()->energy() > 0) {
00552 ((MobileNode *)node_)->log_energy(1);
00553 } else {
00554 ((MobileNode *)node_)->log_energy(0);
00555 }
00556
00557
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
00581 if (em()->energy() > 0) {
00582 ((MobileNode *)node_)->log_energy(1);
00583 } else {
00584 ((MobileNode *)node_)->log_energy(0);
00585 }
00586 }
00587
00588
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 }