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 #include"umts-phy.h"
00031 #include"umts-headers.h"
00032 #include<rng.h>
00033 #include<iostream>
00034 #include<math.h>
00035 #include<ip.h>
00036
00037
00038 static class UmtsPhyClass : public TclClass {
00039 public:
00040 UmtsPhyClass() : TclClass("Module/MPhy/UMTS") {}
00041 TclObject* create(int, const char*const*) {
00042 return (new UmtsPhy());
00043 }
00044 } class_UmtsPhy;
00045
00046
00047 static class MEUmtsPhyClass : public TclClass {
00048 public:
00049 MEUmtsPhyClass() : TclClass("Module/MPhy/UMTS/ME") {}
00050 TclObject* create(int, const char*const*) {
00051 return (new UmtsPhyME());
00052 }
00053 } class_UmtsPhyME;
00054
00055
00056 static class BSUmtsPhyClass : public TclClass {
00057 public:
00058 BSUmtsPhyClass() : TclClass("Module/MPhy/UMTS/BS") {}
00059 TclObject* create(int, const char*const*) {
00060 return (new UmtsPhyBS());
00061 }
00062 } class_UmtsPhyBS;
00063
00064
00065
00066 bool UmtsPhy::mod_initialized = false;
00067 int UmtsPhy::modid = -1;
00068
00069 int UmtsPhy::code_id_counter = 0;
00070
00071
00072
00073 UmtsPhy::UmtsPhy()
00074 : dl_smask_(0), ul_smask_(0), pcTable_(NULL)
00075 {
00076 bind("chip_rate_",&chip_rate_);
00077 bind("spreading_factor_",&spreading_factor_);
00078 bind("bits_per_symbol_",&bits_per_symbol_);
00079 bind("coding_rate_",&coding_rate_);
00080 bind("coding_type_",&coding_type_);
00081 bind("slot_duration_",&slot_duration_);
00082 bind("code_id_",&code_id_);
00083 bind("PERtarget_",&PERtarget_);
00084 bind("SIRtarget_",&SIRtarget_);
00085 bind("maxTxPower_",&maxTxPower_);
00086 bind("minTxPower_",&minTxPower_);
00087 bind("pcStep_",&pcStep_);
00088 bind("alpha_",&alpha_);
00089 bind("PowerCtrlUpdateCmdAtStartRx_",&PowerCtrlUpdateCmdAtStartRx_);
00090 bind("PowerCtrlReadCmdAtStartRx_",&PowerCtrlReadCmdAtStartRx_);
00091
00092
00093
00094 if (!mod_initialized)
00095 {
00096 modid = MPhy::registerModulationType(UMTS_MODNAME);
00097 mod_initialized = true;
00098 }
00099
00100
00101 code_id_counter++;
00102 code_id_ = code_id_counter;
00103 }
00104
00105
00106 UmtsPhyBS::UmtsPhyBS()
00107 {
00108 bind("iuccorr_",&iuccorr_);
00109 }
00110
00111
00112 int UmtsPhy::command(int argc, const char*const* argv)
00113 {
00114
00115 Tcl& tcl = Tcl::instance();
00116
00117 if(argc == 2)
00118 {
00119 if(strcasecmp(argv[1], "getDataRate")==0)
00120 {
00121 tcl.resultf("%f",getDataRate());
00122 return TCL_OK;
00123 }
00124 if(strcasecmp(argv[1], "printPktHeaderInfo")==0)
00125 {
00126 std::cout << "PacketHeader/MPhy "
00127 << sizeof(hdr_MPhy) << " bytes at "
00128 << hdr_MPhy::offset_ << std::endl;
00129 std::cout << "PacketHeader/UMTSPHY "
00130 << sizeof(hdr_umtsphy) << " bytes at "
00131 << hdr_umtsphy::offset_ << std::endl;
00132 std::cout << "PacketHeader/RLC "
00133 << sizeof(hdr_rlc) << " bytes at "
00134 << hdr_rlc::offset_ << std::endl;
00135 std::cout << "PacketHeader/CMN "
00136 << sizeof(hdr_cmn) << " bytes at "
00137 << hdr_cmn::offset_ << std::endl;
00138 std::cout << "PacketHeader/IP "
00139 << sizeof(hdr_ip) << " bytes at "
00140 << hdr_ip::offset_ << std::endl;
00141 std::cout << "size of packet = "
00142 << Packet::hdrlen_ << " bytes"
00143 << std::endl;
00144 return TCL_OK;
00145 }
00146 }
00147
00148 if(argc == 3)
00149 {
00150 if(strcasecmp(argv[1], "setDownlinkSpectralMask")==0)
00151 {
00152
00153 dl_smask_ = dynamic_cast<MSpectralMask*> (TclObject::lookup(argv[2]));
00154 if(!dl_smask_)
00155 return TCL_ERROR;
00156 return TCL_OK;
00157 }
00158
00159 if(strcasecmp(argv[1], "setUplinkSpectralMask")==0)
00160 {
00161
00162 ul_smask_ = dynamic_cast<MSpectralMask*> (TclObject::lookup(argv[2]));
00163 if(!ul_smask_)
00164 return TCL_ERROR;
00165 return TCL_OK;
00166 }
00167 if(strcasecmp(argv[1], "computeSIRtarget")==0)
00168 {
00169 int payload = atoi(argv[2]);
00170 if (payload<=0)
00171 {
00172 printf("Error UmtsPhy::command(%s), payload must be greater than 0, not %d\n", argv[1], payload);
00173 return TCL_ERROR;
00174 }
00175 double sinr = 0;
00176 double ber = sinr2ber(sinr);
00177 double per = (1 - (pow(1-ber, payload * 8)));
00178 while(per>PERtarget_)
00179 {
00180 sinr = sinr + 0.1;
00181 ber = sinr2ber(sinr);
00182 per = (1 - (pow(1-ber, payload * 8)));
00183 }
00184 SIRtarget_ = sinr;
00185 if (debug_>10)
00186 printf("UMTS Power Control Algorithm: PERtarget %f -> SIRtarget %f (payload %d)\n", PERtarget_, SIRtarget_, payload);
00187 return TCL_OK;
00188 }
00189 if(strcasecmp(argv[1], "monitor")==0)
00190 {
00191 int rlcId = atoi(argv[2]);
00192 if (rlcId<0)
00193 {
00194 fprintf(stderr,"UmtsPhy::command(%s), RLC identifier (%d) must be greater than zero\n", argv[1], rlcId);
00195 return TCL_ERROR;
00196 }
00197 addPcEntry(rlcId);
00198 return TCL_OK;
00199 }
00200
00201 }
00202
00203 return MPhy::command(argc, argv);
00204 }
00205
00206
00207 void UmtsPhy::addPcEntry(int id)
00208 {
00209 if (debug_>50)
00210 printf("UMTS-PHY: monitor id %d\n", id);
00211
00212 pcEntry *p = new pcEntry;
00213
00214 p->id = id;
00215 p->TxPower_ = maxTxPower_;
00216 p->powerUp_ = TRUE;
00217
00218 p->next_ = NULL;
00219 if (pcTable_==NULL)
00220 {
00221 pcTable_ = p;
00222 return;
00223 }
00224
00225
00226 pcEntry *q = pcTable_;
00227 pcEntry *last = pcTable_;
00228 while(q!=NULL)
00229 {
00230 if (q->id > id)
00231 break;
00232 last = q;
00233 q = q->next_;
00234 }
00235 if ((last==q)&&(q==pcTable_))
00236 {
00237
00238 p->next_ = pcTable_;
00239 pcTable_ = p;
00240 }
00241 else
00242 {
00243 last->next_ = p;
00244 p->next_ = q;
00245 }
00246 q = pcTable_;
00247 }
00248
00249
00250 pcEntry* UmtsPhy::getPcEntry(int id)
00251 {
00252 pcEntry *q = pcTable_;
00253 while(q!=NULL)
00254 {
00255 if (q->id == id)
00256 {
00257 return q;
00258 }
00259 q = q->next_;
00260 }
00261
00262 if (debug_)
00263 std::cerr << "ID " << id << " not found in PC table" << endl;
00264 return NULL;
00265 }
00266
00267
00268
00269 void UmtsPhy::pcUpdatePi(Packet* p)
00270 {
00271 hdr_rlc *rh = HDR_RLC(p);
00272 hdr_MPhy* ph = HDR_MPHY(p);
00273
00274 pcEntry *q = getPcEntry(rh->src_rlc_id_);
00275 q->Pi = ph->Pi;
00276 }
00277
00278
00279 void UmtsPhy::pcUpdateCmd(Packet* p)
00280 {
00281 hdr_rlc *rh = HDR_RLC(p);
00282 hdr_MPhy* ph = HDR_MPHY(p);
00283
00284 pcEntry *q = getPcEntry(rh->src_rlc_id_);
00285 if (q==NULL)
00286 {
00287 if (debug_>2)
00288 fprintf(stderr,"UmtsPhy::pcUpdateCmd() ignoring NULL pcEntry, rlc_id=%d, this_code_id_=%d\n",
00289 rh->src_rlc_id_,
00290 code_id_);
00291 return;
00292 }
00293
00294
00295 double sinr;
00296
00297 if (PowerCtrlUpdateCmdAtStartRx_)
00298 {
00299
00300
00301
00302 sinr = getPrAfterDeSpreading(p) / (ph->Pn + (q->Pi));
00303 }
00304 else
00305 {
00306
00307
00308 sinr = ph->Pr / (ph->Pn + (ph->Pi));
00309 }
00310
00311 if (sinr < SIRtarget_ * pcStep_)
00312 q->powerUp_ = true;
00313 else
00314 q->powerUp_ = false;
00315
00316 if (debug_>20)
00317 {
00318 printf("UMTS-PHY connection %2d -> %2d has sinr %6.2f SIRtarget %6.2f (Ptx %5.2e) -> %s\n",
00319 rh->src_rlc_id_,
00320 rh->dst_rlc_id_,
00321 sinr,
00322 SIRtarget_,
00323 ph->Pt,
00324 q->powerUp_ ? "UP" : "DOWN");
00325 }
00326
00327 }
00328
00329
00330 void UmtsPhy::pcReadCmd(Packet* p)
00331 {
00332 hdr_rlc *rh = HDR_RLC(p);
00333 hdr_MPhy* ph = HDR_MPHY(p);
00334 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00335
00336 pcEntry *q = getPcEntry(rh->src_rlc_id_);
00337 if (q == NULL)
00338 return;
00339
00340 double oldTxPower = q->TxPower_;
00341
00342
00343
00344 if ((uh->powerUp==TRUE)&&((q->TxPower_*pcStep_)<maxTxPower_))
00345 q->TxPower_ = q->TxPower_ * pcStep_;
00346 if ((uh->powerUp==FALSE)&&((q->TxPower_/pcStep_)>minTxPower_))
00347 q->TxPower_ = q->TxPower_ / pcStep_;
00348
00349
00350 if (debug_==-1)
00351 {
00352 printf("UMTS-MAC %d rx pkt at %.6f: PC command %s %s (%e->%e))",
00353 rh->src_rlc_id_,
00354 Scheduler::instance().clock(),
00355 uh->data == true ? "DATA" : "CTRL" ,
00356 uh->powerUp == true ? "UP" : "DOWN",
00357 oldTxPower,
00358 q->TxPower_);
00359 }
00360
00361 }
00362
00363
00364 int UmtsPhyME::command(int argc, const char*const* argv)
00365 {
00366
00367 Tcl& tcl = Tcl::instance();
00368
00369 if(argc == 2)
00370 {
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 }
00382
00383 return UmtsPhy::command(argc, argv);
00384 }
00385
00386
00387
00388 int UmtsPhy::getModulationType(Packet*)
00389 {
00390 assert(mod_initialized);
00391 return modid;
00392 }
00393
00394
00395 double UmtsPhy::getTxDuration(Packet* p)
00396 {
00397 return (slot_duration_);
00398 }
00399
00400
00401
00402
00403 double UmtsPhy::getTxPower(Packet* p)
00404 {
00405
00406 hdr_rlc *rh = HDR_RLC(p);
00407 hdr_MPhy* ph = HDR_MPHY(p);
00408
00409 pcEntry *q = getPcEntry(rh->dst_rlc_id_);
00410 assert(q);
00411
00412 if (q == NULL)
00413 {
00414 printf("Error UmtsPhy::getTxPower does not find any entry for RLC id %d\n", rh->src_rlc_id_);
00415 exit(1);
00416 }
00417
00418 return(q->TxPower_);
00419 }
00420
00421
00422
00423 void UmtsPhyBS::startTx(Packet* p)
00424 {
00425 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00426
00427 uh->bs_code_id = code_id_;
00428 uh->direction = DIRECTION_DOWNLINK;
00429
00430 UmtsPhy::startTx(p);
00431 }
00432
00433
00434 void UmtsPhyME::startTx(Packet* p)
00435 {
00436 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00437
00438 uh->me_code_id = code_id_;
00439 uh->bs_code_id = bs_code_id_;
00440 uh->direction = DIRECTION_UPLINK;
00441
00442 UmtsPhy::startTx(p);
00443 }
00444
00445
00446 void UmtsPhy::startTx(Packet* p)
00447 {
00448
00449 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00450 uh->coding_type = coding_type_;
00451 uh->coding_rate = coding_rate_;
00452 uh->spreading_factor = spreading_factor_;
00453 uh->bits_per_symbol = bits_per_symbol_;
00454
00455 hdr_rlc *rh = HDR_RLC(p);
00456
00457 pcEntry *q = getPcEntry(rh->dst_rlc_id_);
00458 assert(q);
00459 uh->powerUp = q->powerUp_;
00460
00461 sendDown(p);
00462 }
00463
00464 void UmtsPhy::endTx(Packet* p)
00465 {
00466
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 void UmtsPhy::startRx(Packet* p)
00491 {
00492
00493 if (PowerCtrlUpdateCmdAtStartRx_)
00494 pcUpdateCmd(p);
00495
00496
00497 if (PowerCtrlReadCmdAtStartRx_)
00498 pcReadCmd(p);
00499
00500 }
00501
00502
00503
00504 void UmtsPhyBS::endRx(Packet* p)
00505 {
00506 hdr_MPhy* ph = HDR_MPHY(p);
00507 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00508
00509 assert(uh->direction == DIRECTION_UPLINK);
00510
00511
00512 ph->Pr = getPrAfterDeSpreading(p);
00513 ph->Pi = ph->Pi * iuccorr_;
00514
00515 UmtsPhy::endRx(p);
00516 }
00517
00518
00519
00520 void UmtsPhyME::endRx(Packet* p)
00521 {
00522 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00523 hdr_MPhy* ph = HDR_MPHY(p);
00524
00525 assert(uh->direction == DIRECTION_DOWNLINK);
00526
00527 if (uh->me_code_id != code_id_)
00528 {
00529
00530 Packet::free(p);
00531 return;
00532 }
00533 else
00534 {
00535
00536
00537
00538
00539 ph->Pr = getPrAfterDeSpreading(p);
00540
00541 UmtsPhy::endRx(p);
00542 }
00543 }
00544
00545
00546
00547 void UmtsPhy::endRx(Packet* p)
00548 {
00549
00550
00551
00552 if (! PowerCtrlReadCmdAtStartRx_)
00553 pcReadCmd(p);
00554
00555 if (! PowerCtrlUpdateCmdAtStartRx_)
00556 pcUpdateCmd(p);
00557
00558 pcUpdatePi(p);
00559
00560 calculateErrors(p);
00561
00562 sendUp(p);
00563
00564 }
00565
00566
00567 double UmtsPhyME::getPrAfterDeSpreading(Packet* p)
00568 {
00569 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00570 hdr_MPhy* ph = HDR_MPHY(p);
00571
00572 return (uh->spreading_factor * ph->Pr * (1.0/(1.0+alpha_)));
00573 }
00574
00575
00576
00577 double UmtsPhyBS::getPrAfterDeSpreading(Packet* p)
00578 {
00579 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00580 hdr_MPhy* ph = HDR_MPHY(p);
00581
00582 return (uh->spreading_factor * ph->Pr);
00583 }
00584
00585
00586
00587
00588 void UmtsPhy::calculateErrors(Packet* p)
00589 {
00590 hdr_MPhy* ph = HDR_MPHY(p);
00591 hdr_cmn* ch = HDR_CMN(p);
00592
00593 double sinr = ph->Pr / (ph->Pn + (ph->Pi));
00594 double per = getPacketErrorRate(p, sinr);
00595 double rnd = RNG::defaultrng()->uniform_double();
00596 ch->error() = rnd <= per;
00597
00598 if (debug_) std::cerr << NOW
00599 << " PER=" << per
00600 << " RND=" << rnd
00601 << " ERR=" << ch->error()
00602 << std::endl;
00603
00604
00605 }
00606
00607
00608
00609 double UmtsPhy::getPacketErrorRate(Packet* p, double sinr)
00610 {
00611 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00612 hdr_MPhy* ph = HDR_MPHY(p);
00613
00614
00615 assert(uh->coding_type = CODE_CONVOLUTIONAL);
00616 assert(fabs(uh->coding_rate - 0.5) < 1e-5);
00617
00618 double ber = sinr2ber(sinr);
00619 int nbits = getNumBits(p);
00620 double per = (1 - (pow(1-ber, nbits)));
00621
00622 if (debug_)
00623 std::cerr << NOW
00624 << " SINR=" << sinr
00625 << " NBITS=" << nbits
00626 << " BER=" << ber
00627 << " PER=" << per
00628 << std::endl;
00629
00630 return per;
00631
00632 }
00633
00634
00635 double UmtsPhy::sinr2ber(double sinr)
00636 {
00637 return (0.5*erfc(sqrt(pow(sinr, ZETA_CONVOLUTIONAL_ONEHALF))));
00638 }
00639
00640
00641 int UmtsPhy::getNumBits(Packet* p)
00642 {
00643 hdr_umtsphy* uh = HDR_UMTSPHY(p);
00644 hdr_MPhy* ph = HDR_MPHY(p);
00645 hdr_cmn* ch = HDR_CMN(p);
00646 return (int)(ch->size()*8);
00647
00648
00649
00650 }
00651
00652
00653
00654 double UmtsPhyME::getDataRate()
00655 {
00656
00657
00658
00659 assert(spreading_factor_ > 0);
00660 return (chip_rate_ * bits_per_symbol_ * coding_rate_/ spreading_factor_ );
00661 }
00662
00663
00664 double UmtsPhyBS::getDataRate()
00665 {
00666
00667
00668
00669 assert(chip_rate_ == 3840000);
00670 assert(bits_per_symbol_ == 2);
00671
00672 switch (spreading_factor_)
00673 {
00674 case 4: return (1872000 * coding_rate_);
00675 case 8: return (912000 * coding_rate_);
00676 case 16: return (432000 * coding_rate_);
00677 case 32: return (210000 * coding_rate_);
00678 case 64: return (90000 * coding_rate_);
00679 case 128: return (51000 * coding_rate_);
00680 case 256: return (24000 * coding_rate_);
00681 case 512: return (6000 * coding_rate_);
00682 default: assert(0);
00683 }
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695