|
INET Framework for OMNeT++/OMNEST
|
00001 /* -*- mode:c++ -*- ******************************************************** 00002 * file: SnrEval.cc 00003 * 00004 * author: Marc Loebbers 00005 * Multi-channel support: Levente Meszaros, Andras Varga 00006 * 00007 * copyright: (C) 2004 Telecommunication Networks Group (TKN) at 00008 * Technische Universitaet Berlin, Germany. 00009 * 00010 * This program is free software; you can redistribute it 00011 * and/or modify it under the terms of the GNU General Public 00012 * License as published by the Free Software Foundation; either 00013 * version 2 of the License, or (at your option) any later 00014 * version. 00015 * For further information see file COPYING 00016 * in the top level directory 00017 *************************************************************************** 00018 * part of: framework implementation developed by tkn 00019 ***************************************************************************/ 00020 00021 00022 #include "SnrEval.h" 00023 #include "FWMath.h" 00024 00025 00026 00027 Define_Module(SnrEval); 00028 00029 SnrEval::SnrEval() : rs(this->getId()) 00030 { 00031 } 00032 00033 void SnrEval::initialize(int stage) 00034 { 00035 BasicSnrEval::initialize(stage); 00036 00037 if (stage == 0) 00038 { 00039 gate("radioIn")->setDeliverOnReceptionStart(true); 00040 00041 // read parameters 00042 rs.setChannelNumber(par("channelNumber")); 00043 thermalNoise = FWMath::dBm2mW(par("thermalNoise")); 00044 carrierFrequency = cc->par("carrierFrequency"); // taken from ChannelControl 00045 sensitivity = FWMath::dBm2mW(par("sensitivity")); 00046 pathLossAlpha = par("pathLossAlpha"); 00047 if (pathLossAlpha < (double) (cc->par("alpha"))) 00048 error("SnrEval::initialize(): pathLossAlpha can't be smaller than in " 00049 "ChannelControl. Please adjust your omnetpp.ini file accordingly"); 00050 00051 // initialize noiseLevel 00052 noiseLevel = thermalNoise; 00053 00054 EV << "Initialized channel with noise: " << noiseLevel << " sensitivity: " << sensitivity << 00055 endl; 00056 00057 // initialize the pointer of the snrInfo with NULL to indicate 00058 // that currently no message is received 00059 snrInfo.ptr = NULL; 00060 00061 // no channel switch pending 00062 newChannel = -1; 00063 00064 // Initialize radio state. If thermal noise is already to high, radio 00065 // state has to be initialized as RECV 00066 rs.setState(RadioState::IDLE); 00067 if (noiseLevel >= sensitivity) 00068 rs.setState(RadioState::RECV); 00069 00070 WATCH(noiseLevel); 00071 WATCH(rs); 00072 } 00073 else if (stage == 1) 00074 { 00075 // tell initial value to MAC; must be done in stage 1, because they 00076 // subscribe in stage 0 00077 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00078 nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); 00079 } 00080 else if (stage == 2) 00081 { 00082 // tell initial channel number to ChannelControl; should be done in 00083 // stage==2 or later, because base class initializes myHostRef in that stage 00084 cc->updateHostChannel(myHostRef, rs.getChannelNumber()); 00085 } 00086 } 00087 00088 void SnrEval::finish() 00089 { 00090 BasicSnrEval::finish(); 00091 } 00092 00093 SnrEval::~SnrEval() 00094 { 00095 // delete messages being received 00096 for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it) 00097 delete it->first; 00098 } 00099 00100 void SnrEval::handleMessage(cMessage *msg) 00101 { 00102 if (msg->getArrivalGateId()==uppergateIn && !msg->isPacket()) 00103 { 00104 cPolymorphic *ctrl = msg->removeControlInfo(); 00105 handleCommand(msg->getKind(), ctrl); 00106 delete msg; 00107 } 00108 else 00109 { 00110 BasicSnrEval::handleMessage(msg); // let base class do it 00111 } 00112 } 00113 00124 void SnrEval::handleUpperMsg(AirFrame *frame) 00125 { 00126 if (rs.getState() == RadioState::TRANSMIT) 00127 error("Trying to send a message while already transmitting -- MAC should " 00128 "take care this does not happen"); 00129 00130 if (frame->getControlInfo()!=NULL) 00131 error("Setting control info (here: %s) on frames is not supported", frame->getControlInfo()->getClassName()); 00132 00133 // if a packet was being received, it is corrupted now as should be treated as noise 00134 if (snrInfo.ptr != NULL) 00135 { 00136 EV << "Sending a message while receiving another. The received one is now corrupted.\n"; 00137 00138 // remove the snr information stored for the message currently being 00139 // received. This message is treated as noise now and the 00140 // receive power has to be added to the noiseLevel 00141 00142 // delete the pointer to indicate that no message is being received 00143 snrInfo.ptr = NULL; 00144 // clear the snr list 00145 snrInfo.sList.clear(); 00146 // add the receive power to the noise level 00147 noiseLevel += snrInfo.rcvdPower; 00148 } 00149 00150 // now we are done with all the exception handling and can take care 00151 // about the "real" stuff 00152 00153 // change radio status 00154 rs.setState(RadioState::TRANSMIT); 00155 EV << "sending, changing RadioState to TRANSMIT\n"; 00156 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00157 00158 cMessage *timer = new cMessage(NULL, TRANSM_OVER); 00159 scheduleAt(simTime() + frame->getDuration(), timer); 00160 sendDown(frame); 00161 } 00162 00163 void SnrEval::handleCommand(int msgkind, cPolymorphic *ctrl) 00164 { 00165 if (msgkind==PHY_C_CONFIGURERADIO) 00166 { 00167 // extract new channel number 00168 PhyControlInfo *phyCtrl = check_and_cast<PhyControlInfo *>(ctrl); 00169 int newChannel = phyCtrl->getChannelNumber(); 00170 double newBitrate = phyCtrl->getBitrate(); 00171 delete ctrl; 00172 00173 if (newChannel!=-1) 00174 { 00175 EV << "Command received: change to channel " << newChannel << "\n"; 00176 00177 // do it 00178 if (rs.getChannelNumber()==newChannel) 00179 EV << "Right on that channel, nothing to do\n"; // fine, nothing to do 00180 else if (rs.getState()==RadioState::TRANSMIT) { 00181 EV << "We're transmitting right now, remembering to change after it's completed\n"; 00182 this->newChannel = newChannel; 00183 } else 00184 changeChannel(newChannel); // change channel right now 00185 } 00186 if (newBitrate!=-1) 00187 { 00188 EV << "Command received: change bitrate to " << (newBitrate/1e6) << "Mbps\n"; 00189 00190 // do it 00191 if (rs.getBitrate()==newBitrate) 00192 EV << "Right at that bitrate, nothing to do\n"; // fine, nothing to do 00193 else if (rs.getState()==RadioState::TRANSMIT) { 00194 EV << "We're transmitting right now, remembering to change after it's completed\n"; 00195 this->newBitrate = newBitrate; 00196 } else 00197 setBitrate(newBitrate); // change bitrate right now 00198 } 00199 } 00200 else 00201 error("unknown command (msgkind=%d)", msgkind); 00202 } 00203 00212 void SnrEval::handleSelfMsg(cMessage *msg) 00213 { 00214 if (msg->getKind() == TRANSM_OVER) 00215 { 00216 if (noiseLevel < sensitivity) 00217 { 00218 // set the RadioState to IDLE 00219 rs.setState(RadioState::IDLE); 00220 EV << "transmission over, switch to idle mode (state:IDLE)\n"; 00221 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00222 } 00223 else 00224 { 00225 // set the RadioState to RECV 00226 rs.setState(RadioState::RECV); 00227 EV << "transmission over but noise level too high, switch to recv mode (state:RECV)\n"; 00228 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00229 } 00230 00231 // delete the timer 00232 delete msg; 00233 00234 // switch channel if it needs be 00235 if (newChannel!=-1) 00236 { 00237 changeChannel(newChannel); 00238 newChannel = -1; 00239 } 00240 } 00241 else 00242 error("Internal error: unknown self-message `%s'", msg->getName()); 00243 } 00244 00245 00269 void SnrEval::handleLowerMsgStart(AirFrame * frame) 00270 { 00271 // Calculate the receive power of the message 00272 00273 // calculate distance 00274 const Coord& myPos = getMyPosition(); 00275 const Coord& framePos = frame->getSenderPos(); 00276 double distance = myPos.distance(framePos); 00277 00278 // calculate receive power 00279 double rcvdPower = calcRcvdPower(frame->getPSend(), distance); 00280 00281 // store the receive power in the recvBuff 00282 recvBuff[frame] = rcvdPower; 00283 00284 // if receive power is bigger than sensitivity and if not sending 00285 // and currently not receiving another message and the message has 00286 // arrived in time 00287 // NOTE: a message may have arrival time in the past here when we are 00288 // processing ongoing transmissions during a channel change 00289 if (frame->getArrivalTime() == simTime() && rcvdPower >= sensitivity && rs.getState() != RadioState::TRANSMIT && snrInfo.ptr == NULL) 00290 { 00291 EV << "receiving frame " << frame->getName() << endl; 00292 00293 // Put frame and related SnrList in receive buffer 00294 SnrList snrList; //defined in SnrList.h!! 00295 snrInfo.ptr = frame; 00296 snrInfo.rcvdPower = rcvdPower; 00297 snrInfo.sList = snrList; 00298 00299 // add initial snr value 00300 addNewSnr(); 00301 00302 if (rs.getState() != RadioState::RECV) 00303 { 00304 // publish new RadioState 00305 rs.setState(RadioState::RECV); 00306 EV << "publish new RadioState:RECV\n"; 00307 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00308 } 00309 } 00310 // receive power is too low or another message is being sent or received 00311 else 00312 { 00313 EV << "frame " << frame->getName() << " is just noise\n"; 00314 //add receive power to the noise level 00315 noiseLevel += rcvdPower; 00316 00317 // if a message is being received add a new snr value 00318 if (snrInfo.ptr != NULL) 00319 { 00320 // update snr info for currently being received message 00321 EV << "add new snr value to snr list of message being received\n"; 00322 addNewSnr(); 00323 } 00324 00325 // update the RadioState if the noiseLevel exceeded the threshold 00326 // and the radio is currently not in receive or in send mode 00327 if (noiseLevel >= sensitivity && rs.getState() == RadioState::IDLE) 00328 { 00329 // publish new RadioState 00330 rs.setState(RadioState::RECV); 00331 EV << "publish new RadioState:RECV\n"; 00332 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00333 } 00334 } 00335 } 00336 00337 00348 void SnrEval::handleLowerMsgEnd(AirFrame * frame) 00349 { 00350 // check if message has to be send to the decider 00351 if (snrInfo.ptr == frame) 00352 { 00353 EV << "reception of frame over, preparing to send packet to upper layer\n"; 00354 // get Packet and list out of the receive buffer: 00355 SnrList list; 00356 list = snrInfo.sList; 00357 00358 // delete the pointer to indicate that no message is currently 00359 // being received and clear the list 00360 snrInfo.ptr = NULL; 00361 snrInfo.sList.clear(); 00362 00363 // delete the frame from the recvBuff 00364 recvBuff.erase(frame); 00365 00366 //Don't forget to send: 00367 sendUp(frame, list); 00368 EV << "packet sent to the decider\n"; 00369 } 00370 // all other messages are noise 00371 else 00372 { 00373 EV << "reception of noise message over, removing recvdPower from noiseLevel....\n"; 00374 // get the rcvdPower and subtract it from the noiseLevel 00375 noiseLevel -= recvBuff[frame]; 00376 00377 // delete message from the recvBuff 00378 recvBuff.erase(frame); 00379 00380 // update snr info for message currently being received if any 00381 if (snrInfo.ptr != NULL) 00382 { 00383 addNewSnr(); 00384 } 00385 00386 // message should be deleted 00387 delete frame; 00388 EV << "message deleted\n"; 00389 } 00390 00391 // check the RadioState and update if necessary 00392 // change to idle if noiseLevel smaller than threshold and state was 00393 // not idle before 00394 // do not change state if currently sending or receiving a message!!! 00395 if (noiseLevel < sensitivity && rs.getState() == RadioState::RECV && snrInfo.ptr == NULL) 00396 { 00397 // publish the new RadioState: 00398 EV << "new RadioState is IDLE\n"; 00399 rs.setState(RadioState::IDLE); 00400 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00401 } 00402 } 00403 00404 00408 void SnrEval::addNewSnr() 00409 { 00410 SnrListEntry listEntry; // create a new entry 00411 listEntry.time = simTime(); 00412 listEntry.snr = snrInfo.rcvdPower / noiseLevel; 00413 snrInfo.sList.push_back(listEntry); 00414 } 00415 00416 00422 double SnrEval::calcRcvdPower(double pSend, double distance) 00423 { 00424 double speedOfLight = 300000000.0; 00425 double waveLength = speedOfLight / carrierFrequency; 00426 return (pSend * waveLength * waveLength / (16 * M_PI * M_PI * pow(distance, pathLossAlpha))); 00427 } 00428 00429 00430 void SnrEval::changeChannel(int channel) 00431 { 00432 if (channel == rs.getChannelNumber()) 00433 return; 00434 if (channel < 0 || channel >= cc->getNumChannels()) 00435 error("changeChannel(): channel number %d is out of range (hint: numChannels is a parameter of ChannelControl)", channel); 00436 if (rs.getState() == RadioState::TRANSMIT) 00437 error("changing channel while transmitting is not allowed"); 00438 00439 // if we are currently receiving, must clean that up before moving to different channel 00440 if (rs.getState() == RadioState::RECV) 00441 { 00442 // delete messages being received, and cancel associated self-messages 00443 for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it) 00444 { 00445 AirFrame *frame = it->first; 00446 cMessage *endRxTimer = (cMessage *)frame->getContextPointer(); 00447 delete frame; 00448 delete cancelEvent(endRxTimer); 00449 } 00450 recvBuff.clear(); 00451 } 00452 00453 // clear snr info 00454 snrInfo.ptr = NULL; 00455 snrInfo.sList.clear(); 00456 00457 // do channel switch 00458 EV << "Changing channel to " << channel << "\n"; 00459 00460 rs.setChannelNumber(channel); 00461 cc->updateHostChannel(myHostRef, channel); 00462 ChannelControl::TransmissionList tl = cc->getOngoingTransmissions(channel); 00463 00464 // pick up ongoing transmissions on the new channel 00465 EV << "Picking up ongoing transmissions on new channel:\n"; 00466 for (ChannelControl::TransmissionList::const_iterator it = tl.begin(); it != tl.end(); ++it) 00467 { 00468 AirFrame *frame = *it; 00469 // time for the message to reach us 00470 double distance = myHostRef->pos.distance(frame->getSenderPos()); 00471 simtime_t propagationDelay = distance / LIGHT_SPEED; 00472 00473 // if this transmission is on our new channel and it would reach us in the future, then schedule it 00474 if (channel == frame->getChannelNumber()) 00475 { 00476 EV << " - (" << frame->getClassName() << ")" << frame->getName() << ": "; 00477 00478 // if there is a message on the air which will reach us in the future 00479 if (frame->getTimestamp() + propagationDelay >= simTime()) 00480 { 00481 EV << "will arrive in the future, scheduling it\n"; 00482 00483 // we need to send to each radioIn[] gate 00484 cGate *radioGate = gate("radioIn"); 00485 for (int i = 0; i < radioGate->size(); i++) 00486 sendDirect((cMessage*)frame->dup(), frame->getTimestamp() + propagationDelay - simTime(), frame->getDuration(), this, radioGate->getId() + i); 00487 } 00488 // if we hear some part of the message 00489 else if (frame->getTimestamp() + frame->getDuration() + propagationDelay > simTime()) 00490 { 00491 EV << "missed beginning of frame, processing it as noise\n"; 00492 00493 AirFrame *frameDup = (AirFrame*)frame->dup(); 00494 frameDup->setArrivalTime(frame->getTimestamp() + propagationDelay); 00495 handleLowerMsgStart(frameDup); 00496 bufferMsg(frameDup); 00497 } 00498 else 00499 { 00500 EV << "in the past\n"; 00501 } 00502 } 00503 } 00504 00505 // notify other modules about the channel switch; and actually, radio state has changed too 00506 nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); 00507 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00508 } 00509 00510 void SnrEval::setBitrate(double bitrate) 00511 { 00512 if (this->bitrate == bitrate) 00513 return; 00514 if (bitrate < 0) 00515 error("setBitrate(): bitrate cannot be negative (%g)", bitrate); 00516 if (rs.getState() == RadioState::TRANSMIT) 00517 error("changing the bitrate while transmitting is not allowed"); 00518 00519 EV << "Setting bitrate to " << (bitrate/1e6) << "Mbps\n"; 00520 this->bitrate = bitrate; 00521 00522 //XXX fire some notification? 00523 } 00524