📄 phy-umts.cc
字号:
/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- *//* By Pablo Martin and Paula Ballester, * Strathclyde University, Glasgow. * June, 2003.*//* Copyright (c) 2003 Strathclyde University of Glasgow, Scotland. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code and binary code must contain * the above copyright notice, this list of conditions and the following * disclaimer. * * 2. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed at Strathclyde University of * Glasgow, Scotland. * * 3. The name of the University may not be used to endorse or promote * products derived from this software without specific prior written * permission. * STRATHCLYDE UNIVERSITY OF GLASGOW, MAKES NO REPRESENTATIONS * CONCERNING EITHER THE MERCHANTABILITY OF THIS SOFTWARE OR THE * SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software * is provided "as is" without express or implied warranty of any kind.*/#include <packet.h>#include "delay.h"#include "connector.h"#include "packet.h"#include "random.h"#include "mobilenode.h"#include "address.h"#include <unistd.h>#include "arp.h"#include "ll.h"#include "rlc-umts.h"#include "queue.h"#include "mac.h"#include "phy-umts.h"#include "cmu-trace.h"/////////////////////// bler table /////////////////////////////////double BlerTable::table[2][8] = { {6.31, 7.94, 10, 15.85, 25.12, 100, 2000, 10000000000}, {0.2, 0.15, 0.1, 0.05, 0.02, 0.001, 0.0001, 0.00001} };BlerTable::BlerTable() {}double BlerTable::getbler(double ebno) { int i; double bler; bler = 1e-38; for (i=7; i>-1; i--) { if (table[0][i] > ebno) { bler = table[1][i]; } else { return bler; } } return bler;}/////////////////////////////////////////////////////////////////////int hdr_phy::offset_;// TCL Class for Headerstatic class PhyUmtsHeaderClass : public PacketHeaderClass {public: PhyUmtsHeaderClass() : PacketHeaderClass("PacketHeader/PhyUmts", sizeof(hdr_phy)){ bind_offset(&hdr_phy::offset_); }} class_hdr_phy;// TCL Class for PhyUmtsstatic class PhyUmtsClass : public TclClass {public: PhyUmtsClass() : TclClass("Phy/Umts") {} TclObject* create(int, const char*const*) { return (new PhyUmts()); }} class_phy_umts;// static variablesdouble PhyUmts::slot_time_ = 0;double PhyUmts::rach_slot_time_ = 0;int PhyUmts::verbose_ = {0};static int PhyIndex_ = 0;//constructorPhyUmts::PhyUmts() : LinkDelay(), pUpSlot_(this), pRachUpSlot_(this), pTxPkt_(this), pRxPkt_(this), pPreamble_(this), pCell_(this), pBler_(this), downtarget_(0), uptarget_(0), ll_(0), netif_(0), mac_(0){ int i,j; bind("verbose_", &verbose_); ue_address_ = PhyIndex_++; nodeb_address_ = -1; ue_state_ = 0; pkttoTx_= new PacketQueue(); rachtoTx_= new PacketQueue(); rach_recv_ = NULL; prach_temp_ = new PacketQueue(); data_temp_ = new PacketQueue(); slot_time_= 0.000667 ;//umts slot is of 666.6 microseconds rach_slot_time_= 0.00125 ;//umts slot is of 1.25 miliseconds tx_rate = (int) ((8*80) / slot_time_) ; error_rate_ = 0; rx_power_ = 0; tx_power_ = 0; threshold_ = 4.652e-10; // the value of Rxthresh_ in WirelessPhy *100 //max_num_ms shud be less that MAX_NUM_NODES if (PhyIndex_ > MAX_NUM_NODES) { if (verbose_==1) printf("UE %d at %f PHY: Too many nodes taking part. shud be less than %d \n",ip_ue_,NOW, MAX_NUM_NODES); exit (-1); } radio_active_ = 0; bytes_slot = 0.0; num_preambles_ = 0; wait_ = 0; listen_sccpch_ = 0; listen_sch_ = 0; selected_sc_ = -1; selected_p_ = -1; handover_ = 0; in_seq_ = 0; hin_seq_ = 0; hnodeb_ = 0; count = 0; ip_nodeb_ = -1; ip_ue_ = -1; tti_ = 0.0; power_sch_ = 0; dl_ErrorRate = 1000000000; lastRate = 0; Prx = 0; dlfreq = -1; ulfreq = -1; Ioth = 0; noIoth = 0; BTable = new BlerTable(); for (i=0; i<MAX_NUM_SCRAM; i++) { for (j=0; j< MAX_NUM_SIG + 1; j++) { w_control.free_res_[i][j] = 0; } }// for (i=0; i< MAX_NUM_SCRAM -1; i++) {// w_control.dl_scramb_[i] = 0;// } for (i=0; i< MAX_NUM_RACH; i++) { w_control.free_rach_[i] = 0; } w_control.p_scrambling_ = -1; w_control.signature_ = -1; for (i=0 ; i < MAX_NUM_DPDCH ; i++) { rx_dpdch[i] = NULL; } paging_group_ = -1; up_slot_=0; intr1_ = intr_ ; //reqd for the slot timers intr = intr_ ; intrb = intr_; // initialization of timers pUpSlot_.start((Packet *) (& intr_), 0); pRachUpSlot_.start((Packet *) (& intr1_), 0); pBler_.start((Packet *) (& intrb), 0);}int PhyUmts::command(int argc, const char*const* argv){ Tcl& tcl = Tcl::instance(); if (argc == 3) { if (strcmp(argv[1], "log-target") == 0) { logtarget_ = (NsObject*) TclObject::lookup(argv[2]); if(logtarget_ == 0) return TCL_ERROR; return TCL_OK; } if (strcmp(argv[1], "ll") == 0) { ll_ = (LL*) TclObject::lookup(argv[2]); assert(ll_); return (TCL_OK); } if (strcmp(argv[1], "mac") == 0) { mac_ = (Mac*) TclObject::lookup(argv[2]); assert(mac_); return (TCL_OK); } if (strcmp(argv[1], "netif") == 0) { netif_ = (Phy*) TclObject::lookup(argv[2]); return TCL_OK; } if (strcmp(argv[1], "down-target") == 0) { downtarget_ = (NsObject*) TclObject::lookup(argv[2]); return (TCL_OK); } if (strcmp(argv[1], "up-target") == 0) { uptarget_ = (NsObject*) TclObject::lookup(argv[2]); return (TCL_OK); } } else if (argc == 2) { if (strcmp(argv[1], "down-target") == 0) { tcl.resultf("%s", downtarget_->name()); return (TCL_OK); } if (strcmp(argv[1], "up-target") == 0) { tcl.resultf("%s", uptarget_->name()); return (TCL_OK); } } return LinkDelay::command(argc, argv);}// Return the number of DPDCHs arrivedint PhyUmts::n_rx_dpdch(){ int i, n = 0; for (i=0 ; i < MAX_NUM_DPDCH ; i++) { if (rx_dpdch[i] != NULL) n++; } return (n);}// Packets received from NodeBvoid PhyUmts::recv_from_phy(Packet* p, Handler *h){ int i, j, len; struct hdr_cmn *ch = HDR_CMN(p); struct hdr_phy *ph = HDR_PHY_UMTS(p); // if error, drop packet if ((ch->error() == 1) && (ch->channel_t() != DPCCH)) { Packet::free(p); p = NULL; return; } switch (ch->channel_t()) { case SCH: if (listen_sch_ && (ph->p_scrambling_c() != w_control.p_scrambling_)) { // Trying to find another NodeB with receiving power higher than ours cell_selection(p); } else{ Packet::free(p); p = NULL; } break; case AICH: if ((ph->scrambling_c() == w_control.scram_tx_) && (ph->signature() == w_control.signature_) && (ph->da() == ue_address_)) { // Response of a Preamble, now is possible to tx RACH if (verbose_==1) printf("UE %d at %f PHY: AICH correctly arrived with signature %d\n",ip_ue_,NOW, ph->signature()); pPreamble_.stop(); // stop the preamble timer num_preambles_ = 0; mk_msg_rach(); // send message part RACH } else { Packet::free(p); } break; case PICH: if ((ph->scrambling_c() == w_control.p_scrambling_) && (ph->pi() >= 0)) { // Begin of Paging procedure for some mobile of my paging group if (ph->pi() == paging_group_){ if (verbose_==1) printf("UE %d at %f PHY: PICH with our paging group, listening to PCH\n",ip_ue_, NOW); listen_sccpch_ = 1; // for initiating procedure } } Packet::free(p); break; case PCCPCH: if (ph->scrambling_c() == w_control.p_scrambling_) { // measurements of power if ((ph->rx_power() <= threshold_) && (ph->rx_power() < power_sch_) && (!handover_)) { struct hdr_ll *lh = HDR_LL(p); if (verbose_==1) printf("UE %d at %f PHY: initiating HANDOVER PROCEDURE power arrived %e and power_sch: %e\n" ,ip_ue_, NOW, ph->rx_power(), power_sch_); lh->lltype() = LL_HANDOVER; send_to_rrc(p->copy()); // directive to RRC } power_sch_ = ph->rx_power(); // take measurement from PCCPCH for (i=0; i<MAX_NUM_SCRAM; i++){ // update free resources for (j=0; j<MAX_NUM_SIG + 1; j++){ w_control.free_res_[i][j] = ph->free_resources_[i][j]; } }// for (i=0; i<MAX_NUM_SCRAM - 1; i++){// w_control.dl_scramb_[i] = ph->used_dl_scramb_[i];// } for (i=0; i<MAX_NUM_RACH; i++){ // update free RACH w_control.free_rach_[i] = ph->rach_[i]; } Packet::free(p); } else { Packet::free(p); p = NULL; return; } break; case SCCPCH: // carrying FACH and PCH transport channels if (((ph->scrambling_c() == w_control.p_scrambling_) || (ph->scrambling_c() == selected_sc_)) && (ph->da() == ue_address_)){ struct hdr_ll *lh = HDR_LL(p); //Transport Channel: PCH, for Paging procedure if (lh->lltype() == LL_PAGING) { if (listen_sccpch_) { if (verbose_==1) printf("UE %d at %f PHY: PCH received\n",ip_ue_, NOW); send_to_rrc(p); // directive to RRC listen_sccpch_ = 0; break; } else { Packet::free(p); } } //Transport Channel: FACH, for Setup, Handover and Release procedures and Acknowledge if (lh->lltype() == LL_SETUP_REPLY){ if (ph->bofsec_ == 1) { // begin of sequence struct hdr_ip *ih = HDR_IP(p); paging_group_ = ph->paging_group_; // take paging group if (handover_ = 1) ulfreq = ph->freq(); // take new uplink freq for transmitting handover_ = 0; w_control.p_scrambling_ = selected_sc_; hnodeb_ = nodeb_address_; nodeb_address_ = selected_p_; ip_nodeb_ = ih->saddr(); hin_seq_ = in_seq_; in_seq_ = 0; selected_sc_ = -1; selected_p_ = -1; ch->channel_t() = FACH; // ch mapping uptarget_->recv(p, this); } else { Packet::free(p); p = NULL; } } if (lh->lltype() == LL_RES_REPLY){ if (ph->bofsec_ == 1) { if (verbose_==1) printf("UE %d at %f PHY: FACH with LL_RES_REPLY recived, ul_freq=%d\n",ip_ue_, NOW, ph->freq()); ulfreq = ph->freq(); // take new uplink freq for transmitting ch->channel_t() = FACH; // ch mapping uptarget_->recv(p, this); } else { Packet::free(p); p = NULL; } } if (ch->ptype() == PT_ACK){ // RLC-Acknowledge mode //if (verbose_==1) // printf("UE %d at %f PHY: ACK received in PHY\n",ip_ue_, NOW); ch->channel_t() = FACH; // ch mapping uptarget_->recv(p, this); } if ((lh->lltype() == LL_RELEASE_REPLY) || (lh->lltype() == LL_RELEASE_REQ)){ ch->channel_t() = FACH; // ch mapping uptarget_->recv(p, this); } } else { Packet::free(p); p = NULL; } break; case DPCCH: // Dedicated control channel if (ph->da_ == ue_address_) { // we are the destination if (verbose_==1) printf("UE %d at %f PHY: DPCCH arrived with %d DPDCHs and rx power %e\n", ip_ue_, NOW, ph->dpcch_control().n_dpdch_, ph->rx_power()); Prx = ph->rx_power(); // take power measurements lastRate = ph->dpcch_control().dpdch_rate_; // and rate d_control.n_dpdch_ = ph->dpcch_control().n_dpdch_; len = n_rx_dpdch(); if (len != d_control.n_dpdch_) { // check if all DPDCH have arrived for (j=0; j<len; j++) { Packet::free(rx_dpdch[j]); rx_dpdch[j] = NULL; } Packet::free(p); p = NULL; break; } decode(); // all DPDCHs received, starting decoding Packet::free(p); p = NULL; } else { // For interference modelling if ((ph->sa() != nodeb_address_) && (ph->freq() == dlfreq)) { Ioth += ph->rx_power(); // take power measurements noIoth++; } Packet::free(p); p = NULL; } break; case DPDCH: // Dedicated data channel if (ph->da_ == ue_address_) { // we are the destination len = n_rx_dpdch(); rx_dpdch[len] = p; // store DPDCH packet in buffer } else { Packet::free(p); p = NULL; } break; default: break; } return;}void PhyUmts::recv(Packet* p, Handler *h){ hdr_cmn *ch = HDR_CMN(p); hdr_phy *ph = HDR_PHY_UMTS(p); hdr_ip *ih = HDR_IP(p); hdr_ll *lh = HDR_LL(p); double stime; int i,len; if (ch->direction() == hdr_cmn::UP) { if (ue_state_ == 0){ // UE is switched off, drop packet Packet::free(p); p = NULL; } else { if (ch->channel_t()==PCCPCH) { recv_from_phy(p, this); return; } radioSwitch(ON); stime = TX_Time(p); // simulation of reception time pRxPkt_.start(p, stime); } return; } if (ch->direction() == hdr_cmn::DOWN) { switch (ch->channel_t()) { case RACH: if ((ch->ptype() == PT_ACK) || (lh->lltype() == LL_RELEASE_REQ)) { // ACK from RLC Layer and Release request from RRC layer ph->sa() = ue_address_; mk_msg_rach(p); // send RACH message without preamble return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -