📄 phy-umts-nodeb.cc
字号:
switch (php->c_coding()) { case TURBO: // turbo coding chp->size() = (int)(chp->size()/3); break; case CONV_HALF: // convolutional half chp->size() = (int)(chp->size()/2); break; case CONV_THIRD: // convolutional third chp->size() = (int)(chp->size()/3); break; default: break; } return;}// builds the pdpdchs and dpcch to transmitvoid PhyUmtsNodeb::mk_dpxch(void){ int i, j, uid, k, sf_, k_, index_c_, n_dpdch, freq; double index, temp, sum, mod, total_size, tbytes; nsaddr_t ipdaddr; hdr_cmn * chp; hdr_phy * php; hdr_ip * ihp; // builds dpdchs and dpcch for each UE receiving in its cell for (uid=0; uid < MAX_NUM_UE; uid++) { freq = -1; tbytes = 0.0; ipdaddr = -1; total_size = ue_info_[uid].bytes_slot; if (data_temp_[uid]->length() > 0) { index_c_ = w_control.p_scrambling_; // primary scrambling code Packet* p; if (total_size > MAX_NUM_BYTES_PER_SLOT_DL){ // it is necessary two or more dpdchs n_dpdch = (int)(total_size / MAX_NUM_BYTES_PER_SLOT_DL); mod = (int)(total_size) % MAX_NUM_BYTES_PER_SLOT_DL; if (mod > 0) n_dpdch++; if (n_dpdch > MAX_NUM_DPDCH) n_dpdch = MAX_NUM_DPDCH; // n_dpdch is the number of dpdchs requiered // building dpdchs for (i=0; i<n_dpdch; i++){ Packet* sp = Packet::alloc(); hdr_cmn *chsp = HDR_CMN(sp); hdr_phy *phsp = HDR_PHY_UMTS(sp); phsp->dpdch_control_ = new PacketQueue(); phsp->da() = uid; phsp->size() = 0; phsp->n_dpdch_ = i+1; sum = 0.0; // if there are messages in the queue to be sent while (data_temp_[uid]->length() > 0){ p = data_temp_[uid]->deque(); php = HDR_PHY_UMTS(p); ihp = HDR_IP(p); ipdaddr = ihp->daddr(); freq = php->freq(); sum += php->size(); // check if there is enough space in that DPDCH if (sum <= MAX_NUM_BYTES_PER_SLOT_DL) { // there is enough space for the whole packet php->seqno_ = ue_info_[uid].count; php->eofsec_ = 1; phsp->dpdch_control_->enque(p->copy()); phsp->size() += php->size(); ue_info_[uid].count = 0; Packet::free(p); if (sum == MAX_NUM_BYTES_PER_SLOT_DL){ break; } } else { // no space to allocate all the packet in the current DPDCH sum -= php->size(); temp = php->size(); php->size() = MAX_NUM_BYTES_PER_SLOT_DL - sum; php->seqno_ = ue_info_[uid].count; php->eofsec_ = 0; // sending a part of the message phsp->dpdch_control_->enque(p->copy()); phsp->size() = phsp->size() + MAX_NUM_BYTES_PER_SLOT_DL - sum; php->size() = temp - (MAX_NUM_BYTES_PER_SLOT_DL - sum); ue_info_[uid].count++; // storing the rest of the packet in the buffer data_temp_[uid]->enqueHead(p); break; } } sf_ = 4; // spreading factor // calculates k_ if (i==0 || i==1) k_ = 1; if (i==2 || i==3) k_ = 3; if (i==4 || i==5) k_ = 2; chsp->channel_t()=DPDCH; // ch mapping chsp->next_hop() = ipdaddr; phsp->freq() = freq; // downlink freq for that user send_msg(sp->copy(), index_c_, sf_, k_); // sending DPDCH Packet::free(sp); sp = NULL; } } else { // only 1 DPDCH is needed // building DPDCH packet n_dpdch = 1; // calculate the necessary spreading factor for that application index = total_size; index = (2 * 320 / total_size); index = (int)(log(index)/log(2)); sf_ = 2; for (i=0; i<((int)index - 1); i++) { sf_ *= 2; } // sf_ is the spreading factor chosen Packet* sp = Packet::alloc(); hdr_cmn *chsp = HDR_CMN(sp); hdr_phy *phsp = HDR_PHY_UMTS(sp); phsp->dpdch_control_ = new PacketQueue(); phsp->da() = uid; phsp->size() = 0; phsp->n_dpdch_ = 1; n_dpdch = 1; // extract packets from the buffer to transmit while ((tbytes < total_size) && (data_temp_[uid]->length() > 0)){ p = data_temp_[uid]->deque(); php = HDR_PHY_UMTS(p); ihp = HDR_IP(p); ipdaddr = ihp->daddr(); freq = php->freq(); hdr_rlc_umts *rhp = HDR_RLC_UMTS(p); tbytes += php->size(); if (tbytes <= total_size) { // checks if is possible to send the whole packet php->seqno_ = ue_info_[uid].count; php->eofsec_ = 1; phsp->dpdch_control_->enque(p->copy()); phsp->size() += php->size(); ue_info_[uid].count = 0; Packet::free(p); } else { // no space to allocate all the packet in the current DPDCH tbytes -= php->size(); temp = php->size(); php->size() = total_size - tbytes; php->seqno_ = ue_info_[uid].count; php->eofsec_ = 0; // sending a part of the message phsp->dpdch_control_->enque(p->copy()); phsp->size() = phsp->size() + total_size - tbytes; php->size() = temp - (total_size - tbytes); ue_info_[uid].count++; // storing the rest of the packet in the buffer data_temp_[uid]->enqueHead(p); break; } } k_ = sf_/4; // calculates k_ chsp->channel_t()=DPDCH; // ch mapping phsp->freq() = freq; chsp->next_hop() = ipdaddr; // meter paquete en la cola de tx. send_msg(sp->copy(), index_c_, sf_, k_); // send packet over the air interface Packet::free(sp); sp = NULL; } // building DPCCH Packet* sp = Packet::alloc(); hdr_cmn *chsp = HDR_CMN(sp); hdr_phy *phsp = HDR_PHY_UMTS(sp); // calculate de physical rate transmitted phsp->dpcch_control().dpdch_rate_ = (2 * 2560 / (UMTS_SlotTime * sf_)) * n_dpdch; phsp->da() = uid; chsp->channel_t()=DPCCH; phsp->freq() = freq; phsp->size() = 1.25; phsp->dpcch_control().n_dpdch_ = n_dpdch; if (verbose_==1) printf("Nodeb %d at %f PHY: DPCCH/%dDPDCH with SF=%d sent to UE phyaddr %d in downslot %d\n" ,ip_nodeb_, NOW, phsp->dpcch_control_.n_dpdch_, sf_, phsp->da(), down_slot_); chsp->next_hop() = ipdaddr; send_msg(sp->copy(), index_c_, 256, 0); Packet::free(sp); sp = NULL; continue; } } return;}// sends data packets to the terminalsvoid PhyUmtsNodeb::send_msg(Packet* p, int scram_c, int sf, int k){ int i, ue_address; hdr_cmn *chp = HDR_CMN(p); hdr_phy *php = HDR_PHY_UMTS(p); // get the ue destination address ue_address = ue_id[php->da()]; php->sa_ = nodeb_address_; // source address php->da_ = ue_address; // destination address php->scrambling_c_ = scram_c; // scrambling code php->sf_ = sf; // spreading factor php->k_ = k; // k for the channelisation code // calculates size in bytes depending on the spreading factor chosen chp->size_=(int)(UMTS_TBLength / (php->sf_ * 8)); // bytes if ((UMTS_TBLength % (php->sf_ * 8)) != 0){ chp->size_++; } chp->error()= 0; pkttoTx_->enque(p->copy()); // prepare pkt to tx onto air interface Packet::free(p); p=NULL; return;}// sends directives directly to the RRC layervoid PhyUmtsNodeb::send_to_rrc(Packet* p)// method for communicating with the RRC layer. Possible types of messages are:// - PT_RRC_FAILURE Failure when trying to tx RACH// - LL_HANDOVER For handover decission// - LL_PAGING Check the paging group broadcasted in PICH{ hdr_cmn *chp = HDR_CMN(p); hdr_phy *php = HDR_PHY_UMTS(p); chp->direction_ = hdr_cmn::UP; // puts direction UP chp->error()= 0; ll_->recv(p, (Handler*) 0); // sends to RRC}// Turn on / off the radiovoid PhyUmtsNodeb::radioSwitch(int i){ radio_active_ = i; EnergyModel *em = netif_->node()->energy_model(); if (i == ON) { // turns the radio on if (em && em->sleep()){ em->set_node_sleep(0); } } if (i == OFF) { // turns the radio off if (em && !em->sleep()) { em->set_node_sleep(1); }; }}// calculates the transmission timedouble PhyUmtsNodeb::TX_Time(Packet *p) { double len=(HDR_CMN(p))->size(); double t = (double)(len*8)/tx_rate; return t;}// transmits the packet to the terminalsvoid PhyUmtsNodeb::tx_to_ue(Packet *p){ double stime; double temp; hdr_cmn* ch = HDR_CMN(p); hdr_phy* ph = HDR_PHY_UMTS(p); ph->rx_power() = 0; stime = TX_Time(p); // calculate tx time// if (verbose_==1)// printf("Nodeb %d at %f PHY: txing pkt, sendtime=%f, size=%d\n", ip_nodeb_, NOW, stime, ch->size()); pTxPkt_.start(p->copy(), stime); // start tx timer downtarget_->recv(p, this);}// store bytes_slot for the UEvoid PhyUmtsNodeb::slot_bytes(int pdest, double bytes){ int j; j = look_for(pdest); ue_info_[j].bytes_slot = bytes; return;}// Remove UE from ue_info_[]void PhyUmtsNodeb::remove_ue(int addr){ int j = look_for(addr); // Remove this ue from our structures ue_info_[j].paging_group = -1; ue_info_[j].bytes_slot = 0.0; ue_info_[j].in_seq_ = 0; ue_info_[j].count = 0; ue_info_[j].ul_ErrorRate = 1000000000; ue_info_[j].lastRate = 0; ue_info_[j].Prx = 0; ue_info_[j].ul_freq = -1; ue_info_[j].nSamples = 0; ue_info_[j].IntPower = 0; ue_id[j] = -1; return;}/********************************* HANDLERS **********************************/void PhyUmtsNodeb::PagingHandler(Event *e){ // We have not received response to the paging. Send failure message to RRC if (verbose_==1) printf("Nodeb %d at %f PHY: No response to the paging procedure....\n", ip_nodeb_, NOW); hdr_cmn *ch = HDR_CMN(pch_recv_); ch->channel_t() = TO_RRC; ch->ptype() = PT_RRC_FAILURE; ch->direction() = hdr_cmn::UP; wait_ = 0; send_to_rrc(pch_recv_);}// Called after transmission a packet ie when txTimer expires.// Frees the pkt. Turns off the radio.void PhyUmtsNodeb::sendHandler(Event *e){ Packet::free((Packet *)e); radioSwitch(OFF); return;}// Called when BlerTimer expires.// Timer for calculating the Interferencevoid PhyUmtsNodeb::blerHandler(Event *e){ double Eb_No, bler, I = 0; int i, j = 0; // Restart timer for next time. pBler_.start((Packet *)e, 5*UMTS_FrameTime); for (i=0; i<MAX_NUM_UE; i++) { if (ue_info_[i].ul_freq < 0) { // there is not interference for i freq continue; } if ((ue_info_[i].lastRate > 0) && (noIoth[ue_info_[i].ul_freq] > 0)) { // if there has been any interference if ((noIoth[ue_info_[i].ul_freq] - ue_info_[i].nSamples) > 0) { I = (Ioth[ue_info_[i].ul_freq] - ue_info_[i].IntPower)/ (noIoth[ue_info_[i].ul_freq] - ue_info_[i].nSamples); Eb_No = (CHIP_RATE * ue_info_[i].Prx) / (ue_info_[i].lastRate * I); } else { // no interference at all Eb_No = 1e38; } } else { // no interference at all Eb_No = 1e38; } bler = BTable->getbler(Eb_No); // consult table (Eb_No) ue_info_[i].ul_ErrorRate = (int)(1/bler) + 1; if (verbose_) printf("Nodeb %d at %f PHY: blerHandler,,, {lastRate Ioth noIoth I Prx EbNo ue freq bler ul_ErrorRate}\n[%f %e %d %e %e %e %d %d %e %lu]\n", ip_nodeb_, NOW, ue_info_[i].lastRate, Ioth[ue_info_[i].ul_freq],noIoth[ue_info_[i].ul_freq], I, ue_info_[i].Prx, Eb_No, ue_id[i],ue_info_[i].ul_freq, bler, ue_info_[i].ul_ErrorRate); error[j] = ue_info_[i].ul_ErrorRate; addr[j] = ue_id[i]; ue_info_[i].nSamples = 0; ue_info_[i].IntPower = 0; j++; } for (i=0; i<MAX_NUM_FREQ; i++){ Ioth[i] = 0; noIoth[i] = 0; } // put bounds to the arrays error[] and addr[] error[j] = 0; addr[j] = -1; mac_->ul_interference(addr, error); // send the results to MAC return;}// Called after the reception of a packet when RxPktNodebTimer expires.// Turns the radio off and call recv_from_phyvoid PhyUmtsNodeb::recvHandler(Event *e){ u_int32_t dst, src; int size; Packet * p = (Packet * )e; radioSwitch(OFF); // turn the radio OFF recv_from_phy(p, this); // send the packet to analize in method recv_from_phy() return;}// Called when DownSlotUmtsTimer expiersvoid PhyUmtsNodeb::downslotHandler(Event *e){ int i,len; // Restart timer for next slot. pDownSlot_.start((Packet *)e, slot_time_); mk_dpxch(); // DPDCH Multiplexing and DPCCH creation mk_pccpch(); // PCCPCH tx while (pkttoTx_->length() > 0) { //start transmission radioSwitch(ON); // turn the radio ON tx_to_ue(pkttoTx_->deque()); // transmit to UE } if (pchtoTx_->length() > 0) { radioSwitch(ON); // turn the radio ON tx_to_ue(pchtoTx_->deque()); // transmit to UE } // program next slot down_slot_ ++; if (down_slot_ == SLOTS_PER_FRAME) { down_slot_ = 0; //ie wrap around. } // load broadcast information for the next slot. if (down_slot_ == 0) mk_sch(); // SCH tx // empty dl_used_scrambling codes array./* for (i=0; i< MAX_NUM_SCRAM -1; i++) { w_control.dl_scramb_[i] = 0; }*/ return;}// Called when AichSlotUmtsTimer expires.void PhyUmtsNodeb::aichslotHandler(Event *e){ int i,len; // Restart timer for next slot. pAichSlot_.start((Packet *)e, aich_slot_time_); // transmit 1 packet from queue if (aichtoTx_->length() > 0) { //start transmission radioSwitch(ON);// if (verbose_==1)// printf("Nodeb %d at %f PHY: in upslothandler. AICH TX slot=%d \n",// ip_nodeb_, NOW, down_slot_ ); tx_to_ue(aichtoTx_->deque()); // transmit to UE } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -