PHYenb.cc 10.5 KB
Newer Older
C
x  
calincerchez 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

#include "PHYenb.h"
C
calincerchez 已提交
17
#include "LTEChannelControl.h"
C
x  
calincerchez 已提交
18 19 20

Define_Module(PHYenb);

C
calin cerchez 已提交
21
PHYenb::PHYenb() : PHY() {
C
x  
calincerchez 已提交
22 23
    dlBandwith = 6;
    ulBandwith = 6;
C
calincerchez 已提交
24 25

    dlReqBCHpdu = NULL;
C
x  
calincerchez 已提交
26 27 28
}

PHYenb::~PHYenb() {
C
calincerchez 已提交
29 30 31 32
    for (unsigned char i = 0; i < nDLsymb * 2; i++) {
        if (dlSubframe[i])
            delete dlSubframe[i];
    }
C
x  
calincerchez 已提交
33 34 35 36
}

void PHYenb::initialize(int stage) {
    // TODO - Generated method body
C
calin cerchez 已提交
37
	PHY::initialize(stage);
C
x  
calincerchez 已提交
38 39 40 41 42 43 44 45 46 47

    if (stage == 2) {
        cc->setRadioChannel(myRadioRef, PRACH);
        cc->setRadioChannel(myRadioRef, PUSCH);
    }

    if (stage == 4) {
        fsm = cFSM("fsm-PHYenb");
        fsm.setState(IDLE);

C
calincerchez 已提交
48 49 50 51 52 53
        nb = NotificationBoardAccess().get();

        nb->subscribe(this, PARAMRequest);
        nb->subscribe(this, CONFIGRequest);
        nb->subscribe(this, STARTRequest);
        nb->subscribe(this, TXRequest);
C
calin cerchez 已提交
54
        nb->subscribe(this, DLCONFIGRequest);
C
x  
calincerchez 已提交
55 56 57
    }
}

58 59
void PHYenb::handleMessage(cMessage *msg) {
	if (msg->isSelfMessage()) {
C
calincerchez 已提交
60
		if (msg == symbolTimer) {
C
calincerchez 已提交
61 62 63 64 65 66 67 68
            if (symb == 0 && slot % 2 == 0) {
                cleanup();

                SubframeIndication *sfInd = new SubframeIndication();
                sfInd->setSf(sf);
                sfInd->setSfn(sfn);
                nb->fireChangeNotification(SUBFRAMEIndication, sfInd);
                delete sfInd;
C
calincerchez 已提交
69

C
calincerchez 已提交
70 71 72 73 74 75
                buildSubframe();
            }

            sendSymbol();

		    this->cancelEvent(symbolTimer);
C
calincerchez 已提交
76 77
            this->scheduleAt(simTime() + symbPeriod, symbolTimer);

C
calincerchez 已提交
78 79 80 81 82
            symb = (symb + 1) % nDLsymb;
            if (symb == 0) {
                slot = (slot + 1) % 20;
                sf = slot / 2;

C
calincerchez 已提交
83
                if (sf == 0)
C
calincerchez 已提交
84
                    sfn++;
C
calincerchez 已提交
85
            }
86 87 88 89
		}
	}
}

C
x  
calincerchez 已提交
90
void PHYenb::handleUpperMessage(cMessage *msg) {
C
calin cerchez 已提交
91
    EV << "LTE-PHYenb: Receiving message with id = " << msg->getKind() << " from upper layer. Buffering the received message.\n";
C
calincerchez 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
//    LTEControlInfo *ctrl = check_and_cast<LTEControlInfo*>(msg->removeControlInfo());
//    TransportBlock *tb = new TransportBlock();
//    tb->setName(msg->getName());
//    tb->encapsulate(PK(msg));
//    switch(ctrl->getChannel()) {
//        case BCH:
//        	// TODO repetition of MIB + get the tti rest at PHYue
//            tb->setChannelNumber(PBCH);
//            break;
//        case DLSCH0:
//            tb->setChannelNumber(PDSCH0);
//            break;
//        case DLSCH1:
//            tb->setChannelNumber(PDSCH1);
//            break;
//        default:
//            break;
//    }
//    buffer[msg->getKind()] = tb;
C
x  
calincerchez 已提交
111 112
}

C
calin cerchez 已提交
113 114 115 116
void PHYenb::handleRadioMessage(cMessage *msg) {
    PhysicalResourceBlock *prb = check_and_cast<PhysicalResourceBlock*>(msg);
    EV << "LTE-PHYenb: Receiving message from ";

C
calincerchez 已提交
117 118 119 120 121 122 123 124 125 126 127 128
//    if (prb->getChannelNumber() == PRACH) {
//    	EV << "PRACH.\n";
//    	RAPreamble *raPreamble = check_and_cast<RAPreamble*>(prb);
//    	RachIndication *rachInd = new RachIndication();
//    	rachInd->setTti(tti);
//    	rachInd->setPreamblesArraySize(1);
//    	RachPreamble rachPrbl = RachPreamble();
//    	rachPrbl.setPreamble(raPreamble->getRapid());
//    	rachPrbl.setRnti(raPreamble->getRnti());
//    	rachInd->setPreambles(0, rachPrbl);
//    	nb->fireChangeNotification(RACHIndication, rachInd);
//    }
C
x  
calincerchez 已提交
129 130
}

C
calincerchez 已提交
131 132 133 134 135 136 137
void PHYenb::buildSubframe() {
    EV << "LTE-PHYenb: Building downlink subframe for sfn = " << sfn << " and sf = " << (unsigned)sf << ".\n";
	for (unsigned char i = 0; i < nDLsymb * 2; i++) {
		dlSubframe[i] = new PHYSymbol();
		dlSubframe[i]->setResArraySize(nDLrb * nRBsc);
		dlSubframe[i]->setChannelNumber(Downlink);
	}
C
calincerchez 已提交
138 139

    unsigned char ssOffset = (nDLrb * nRBsc) / 2 - 31;
C
calincerchez 已提交
140
    unsigned char vShift = nCellId % 6;
C
calincerchez 已提交
141 142

    // PSS
C
calincerchez 已提交
143 144 145 146 147
    if ((slot == 0 || slot == 10)) {
    	PHYSymbol *symbol = dlSubframe[nDLsymb - 1];
    	unsigned char k = ssOffset;
        for (; k < ssOffset + 62; k++) {
            symbol->setRes(k, PSS);
C
calincerchez 已提交
148
        }
C
calincerchez 已提交
149 150
        PSSSignal *pss = new PSSSignal();
        pss->setCellIdInGroup(n2id);
C
calincerchez 已提交
151
        buffer[nDLsymb - 1][k - 1] = pss;
C
calincerchez 已提交
152 153 154
    }

    // SSS
C
calincerchez 已提交
155 156 157 158 159
    if ((slot == 0 || slot == 10)) {
    	PHYSymbol *symbol = dlSubframe[nDLsymb - 2];
    	unsigned char k = ssOffset;
        for (; k < ssOffset + 62; k++) {
            symbol->setRes(k, SSS);
C
calincerchez 已提交
160
        }
C
calincerchez 已提交
161 162 163
        SSSSignal *sss = new SSSSignal();
        sss->setCellGroupId(n1id);
        sss->setSf(sf);
C
calincerchez 已提交
164
        buffer[nDLsymb - 2][k - 1] = sss;
C
calincerchez 已提交
165 166 167
    }

    // RS
C
calincerchez 已提交
168 169 170 171 172 173 174 175 176
    PHYSymbol *symbol1 = dlSubframe[0];
    PHYSymbol *symbol2 = dlSubframe[nDLsymb - 3];
    unsigned char v1 = 0;
    unsigned char v2 = 3;
    unsigned char rsOffset1 = (v1 + vShift) % 6;
    unsigned char rsOffset2 = (v2 + vShift) % 6;
    for (unsigned char i = 0; i < 2 * nDLrb - 1; i++) {
    	symbol1->setRes(rsOffset1 + 6 * i, RS);
    	symbol2->setRes(rsOffset2 + 6 * i, RS);
C
calincerchez 已提交
177
    }
C
calincerchez 已提交
178 179 180 181 182
    ReferenceSignal *refSig = new ReferenceSignal();
    refSig->setCellId(nCellId);
    refSig->setNcp(ncp);
    buffer[0][2 * nDLrb - 1] = refSig->dup();
    buffer[nDLsymb - 3][2 * nDLrb - 1] = refSig;
C
calincerchez 已提交
183 184

    // PBCH
C
calincerchez 已提交
185
    if (dlReqBCHpdu && slot == 1) {
C
calincerchez 已提交
186
        unsigned char pbchOffset = nDLrb * nRBsc / 2 - 36;
C
calincerchez 已提交
187 188 189 190 191 192 193 194 195 196 197 198 199 200
        for (unsigned char s = 0; s < 4; s++) {
            PHYSymbol *symbol = dlSubframe[s];
            for (unsigned char k = pbchOffset; k < pbchOffset + 72; k++) {
                symbol->setRes(k, PBCH);
            }
        }
    }
}

void PHYenb::cleanup() {
    if (sfn % 4 == 0 && sf == 0) {
        if (dlReqBCHpdu) {
            delete dlReqBCHpdu;
            dlReqBCHpdu = NULL;
C
calincerchez 已提交
201
        }
C
calincerchez 已提交
202
    }
C
calincerchez 已提交
203 204 205 206 207 208 209 210 211 212 213 214
}

void PHYenb::sendSymbol() {
	PHYSymbol *symbol = dlSubframe[symb + (slot % 2) * nDLsymb];

	TransmissionBuffer::iterator l = buffer.find(symb + (slot % 2) * nDLsymb);
	if (l != buffer.end()) {
	    for (PHYFrames::iterator k = l->second.begin(); k != l->second.end(); ++k) {
	        setData(k->second);
	        l->second.erase(k);
	    }
	}
C
calincerchez 已提交
215

C
calincerchez 已提交
216 217
	sendToChannel(symbol);
	dlSubframe[symb + (slot % 2) * nDLsymb] = NULL;
C
calincerchez 已提交
218 219
}

C
calincerchez 已提交
220
void PHYenb::setData(PHYFrame *frame) {
C
calincerchez 已提交
221
    if (dynamic_cast<LTEChannelControl*>(cc) != NULL) {
C
calincerchez 已提交
222
        dynamic_cast<LTEChannelControl*>(cc)->setData(frame);
C
calincerchez 已提交
223 224 225
    }
}

C
calin cerchez 已提交
226 227 228 229 230 231
void PHYenb::stateEntered(int category, const cPolymorphic *details) {
	PHY::stateEntered(category, details);

	if (fsm.getState() == RUNNING) {
		if (category == DLCONFIGRequest) {
			DlConfigRequest *dlCfgReq = check_and_cast<DlConfigRequest*>(details);
C
calincerchez 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244
		    for (unsigned i = 0; i < dlCfgReq->getPdusArraySize(); i++) {
		        DlConfigRequestPduPtr pdu = dlCfgReq->getPdus(i);
		        if (pdu->getType() == BchPdu) {
		            dlReqBCHpdu = dynamic_cast<DlConfigRequestBchPdu*>(pdu);
		        }
//		    		DlConfigRequestPduPtr pdu = dlCfgReq->getPdus(i)->dup();
//		    		EV << "LTE-PHYenb: Received DLCONFIGRequest for PDU with type = " << (unsigned)pdu->getType() << ".\n";
//		    		if (pdu->getType() == DciDlPdu) {
//		    			sendDCIFormat(pdu);
//		    		} else {
//		    			dlCfgReqs[dlCfgReq->getTti()].push_back(pdu);
//		    		}
		    }
C
calin cerchez 已提交
245
		} else if (category == TXRequest) {
C
calincerchez 已提交
246 247 248 249 250 251 252 253 254 255 256
//			TxRequest *txReq = check_and_cast<TxRequest*>(details);
//			for (unsigned i = 0; i < txReq->getPdusArraySize(); i++) {
//				TxRequestPdu pdu = txReq->getPdus(i);
//				if (dlCfgReqs.find(txReq->getTti()) != dlCfgReqs.end()) {
//					for (unsigned j = 0; j < pdu.getMsgKindsArraySize(); j++) {
//						unsigned short msgKind = pdu.getMsgKinds(j);
//						EV << "LTE-PHYenb: Received TXRequest for PDU with id = " << msgKind << ".\n";
//						txReqs[pdu.getPduIndex()].push_back(msgKind);
//					}
//				}
//			}
C
calin cerchez 已提交
257 258
		}
	}
C
calincerchez 已提交
259
//	delete details;
C
x  
calincerchez 已提交
260 261
}

C
calin cerchez 已提交
262 263 264
void PHYenb::sendBufferedData() {
	unsigned short rnti = 0;

C
calincerchez 已提交
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
//	DlConfigRequests::iterator dlCfgReqsIt = dlCfgReqs.find(tti);
//	if (dlCfgReqsIt != dlCfgReqs.end()) {	// first check downlink configuration requests
//		EV << "LTE-PHYenb: Found DLConfigRequest for tti = " << tti << ".\n";
//
//		while(!dlCfgReqsIt->second.empty()) {
//			DlConfigRequestPduPtr dlCfgReqPdu = dlCfgReqsIt->second.front();
//
//			// find rnti to add to transport block
//			if (dlCfgReqPdu->getType() == DlschPdu) {
//				DlConfigRequestDlschPdu *dlCfgReqDlschPdu = check_and_cast<DlConfigRequestDlschPdu*>(dlCfgReqPdu);
//				rnti = dlCfgReqDlschPdu->getRnti();
//			}
//
//			dlCfgReqsIt->second.pop_front();
//			TxRequests::iterator txReqsIt = txReqs.find(dlCfgReqPdu->getPduIndex());
//			if (txReqsIt != txReqs.end()) {	// second check transmission requests
//				EV << "LTE-PHYenb: Found TxRequest for pduIndex = " << dlCfgReqPdu->getPduIndex() << ".\n";
//
//				while(!txReqsIt->second.empty()) {
//					short msgKind = txReqsIt->second.front();
//					txReqsIt->second.pop_front();
//
//					TransmissionBuffer::iterator bufferIt = buffer.find(msgKind);
//					if (bufferIt != buffer.end()) {	// send transportblock from the buffer
//
//						EV << "LTE-PHYenb: Sending buffered transport block with id = " << msgKind << " to the air.\n";
//						TransportBlock *tb = bufferIt->second;
//						tb->setRnti(rnti);
//						sendToChannel(tb);
//						buffer.erase(bufferIt);
//					}
//				}
//			}
//			delete dlCfgReqPdu;
//		}
//		dlCfgReqs.erase(dlCfgReqsIt);
//	}
C
x  
calincerchez 已提交
302 303 304 305 306
}

void PHYenb::sendDCIFormat(DlConfigRequestPduPtr pdu) {
    DlConfigRequestDciDlPdu *dciPdu = check_and_cast<DlConfigRequestDciDlPdu*>(pdu);
    DCIFormat *dci = new DCIFormat();
C
calin cerchez 已提交
307
    dci->setName("DCIFormat");
C
x  
calincerchez 已提交
308
    dci->setRnti(dciPdu->getRnti());
C
calin cerchez 已提交
309
//    dci->setRntiType(dciPdu->getRntiType());
C
x  
calincerchez 已提交
310 311 312
    dci->setChannelNumber(PDCCH);
    sendToChannel(dci);
}
C
calin cerchez 已提交
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
//
//bool PHYenb::findAndRemoveDlConfigRequestPdu(unsigned short pduIndex) {
//    DlConfigRequestPdus::iterator i = dlCfgReqPdus.find(pduIndex);
//    if (i != dlCfgReqPdus.end()) {
//    	delete i->second;
//        dlCfgReqPdus.erase(i);
//        return true;
//    } else {
//        return false;
//    }
//}
//
//bool PHYenb::findAndRemoveTxRequestPdu(unsigned msgId) {
//    TxRequestPdus::iterator i = txReqPdus.find(msgId);
//    if (i != txReqPdus.end()) {
//    	txReqPdus.erase(i);
//        return true;
//    } else {
//        return false;
//    }
//}