#include <SnrEval.h>
Inheritance diagram for SnrEval:
This module keeps track of the noise level of the channel.
When receiving a packet this module updates the noise level of the channel. Based on the receive power of the packet it is processed and handed to upper layers or just treated as noise.
After the packet is completely received the snir information is attached and it is handed to the decider module.
The snir information is a SnrList that lists all different snr levels together with the point of time (simTime()) when they started.
On top of that this module manages the RadioState, and posts notifications on NotificationBoard whenever it changes. The radio state gives information about whether this module is sending a packet, receiving a packet or idle. This information can be accessed via the NotificationBoard by other modules, e.g. a CSMAMacLayer.
Public Member Functions | |
SnrEval () | |
void | changeChannel (int channel) |
change transmitter and receiver to a new channel. This method throws an error if the radio state is transmit. Messages that are already sent to the new channel and would reach us in the future - thus they are on the air - will be received correctly. | |
void | setBitrate (double bitrate) |
change the bitrate to the given value. This method throws an error if the radio state is transmit. | |
Protected Types | |
typedef std::map< AirFrame *, double > | RecvBuff |
Typedef used to store received messages together with receive power. | |
enum | { TRANSM_OVER } |
Enum to store self message kind()s. More... | |
Protected Member Functions | |
virtual void | initialize (int) |
Initialize variables and publish the radio status. | |
virtual void | finish () |
virtual | ~SnrEval () |
void | handleMessage (cMessage *msg) |
Called every time a message arrives. | |
virtual void | handleUpperMsg (AirFrame *) |
virtual void | handleSelfMsg (cMessage *) |
virtual void | handleCommand (int msgkind, cPolymorphic *ctrl) |
virtual void | handleLowerMsgStart (AirFrame *) |
Buffer the frame and update noise levels and snr information. | |
virtual void | handleLowerMsgEnd (AirFrame *) |
Unbuffer the frame and update noise levels and snr information. | |
double | calcRcvdPower (double pSend, double distance) |
Calculates the power with which a packet is received. | |
virtual int | channelNumber () const |
void | addNewSnr () |
updates the snr information of the relevant AirFrames | |
Protected Attributes | |
SnrStruct | snrInfo |
State: SnrInfo stores the snrList and the the recvdPower for the message currently being received, together with a pointer to the message. | |
RecvBuff | recvBuff |
State: A buffer to store a pointer to a message and the related receive power. | |
RadioState | rs |
State: the current RadioState of the NIC; includes channel number. | |
int | newChannel |
State: if not -1, we have to switch to that channel once we finished transmitting. | |
double | newBitrate |
State: if not -1, we have to switch to that bitrate once we finished transmitting. | |
double | noiseLevel |
State: the current noise level of the channel. | |
double | carrierFrequency |
Configuration: The carrier frequency used. It is read from the ChannelControl module. | |
double | thermalNoise |
Configuration: Thermal noise on the channel. Can be specified in omnetpp.ini. Default: -100 dBm. | |
double | sensitivity |
Configuration: Defines up to what Power level (in dBm) a message can be understood. If the level of a received packet is lower, it is only treated as noise. Can be specified in omnetpp.ini. Default: -85 dBm. | |
double | pathLossAlpha |
Configuration: Path loss coefficient. Can be specified in omnetpp.ini. If not it is read from the ChannelControl module. This value CANNOT be smaller than the one specified in the ChannelControl module, or the simulation will exit with an error! | |
Classes | |
struct | SnrStruct |
Struct to store a pointer to the message, rcvdPower AND a SnrList, needed in SnrEval::addNewSnr. More... |
|
Typedef used to store received messages together with receive power.
|
|
Enum to store self message kind()s.
00107 { 00109 TRANSM_OVER 00110 };
|
|
00029 : rs(this->id()) 00030 { 00031 }
|
|
00092 { 00093 // delete messages being received 00094 for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it) 00095 delete it->first; 00096 }
|
|
updates the snr information of the relevant AirFrames The Snr information of the buffered message is updated. 00407 { 00408 SnrListEntry listEntry; // create a new entry 00409 listEntry.time = simTime(); 00410 listEntry.snr = snrInfo.rcvdPower / noiseLevel; 00411 snrInfo.sList.push_back(listEntry); 00412 }
|
|
Calculates the power with which a packet is received. This function simply calculates with how much power the signal arrives "here". If a different way of computing the path loss is required this function can be redefined. 00421 { 00422 double speedOfLight = 300000000.0; 00423 double waveLength = speedOfLight / carrierFrequency; 00424 return (pSend * waveLength * waveLength / (16 * M_PI * M_PI * pow(distance, pathLossAlpha))); 00425 }
|
|
change transmitter and receiver to a new channel. This method throws an error if the radio state is transmit. Messages that are already sent to the new channel and would reach us in the future - thus they are on the air - will be received correctly.
00429 { 00430 if (channel == rs.getChannelNumber()) 00431 return; 00432 if (channel < 0 || channel >= cc->getNumChannels()) 00433 error("changeChannel(): channel number %d is out of range (hint: numChannels is a parameter of ChannelControl)", channel); 00434 if (rs.getState() == RadioState::TRANSMIT) 00435 error("changing channel while transmitting is not allowed"); 00436 00437 // if we are currently receiving, must clean that up before moving to different channel 00438 if (rs.getState() == RadioState::RECV) 00439 { 00440 // delete messages being received, and cancel associated self-messages 00441 for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it) 00442 { 00443 AirFrame *frame = it->first; 00444 cMessage *endRxTimer = (cMessage *)frame->contextPointer(); 00445 delete frame; 00446 delete cancelEvent(endRxTimer); 00447 } 00448 recvBuff.clear(); 00449 } 00450 00451 // clear snr info 00452 snrInfo.ptr = NULL; 00453 snrInfo.sList.clear(); 00454 00455 // do channel switch 00456 EV << "Changing channel to " << channel << "\n"; 00457 00458 rs.setChannelNumber(channel); 00459 cc->updateHostChannel(myHostRef, channel); 00460 ChannelControl::TransmissionList tl = cc->getOngoingTransmissions(channel); 00461 00462 // pick up ongoing transmissions on the new channel 00463 EV << "Picking up ongoing transmissions on new channel:\n"; 00464 for (ChannelControl::TransmissionList::const_iterator it = tl.begin(); it != tl.end(); ++it) 00465 { 00466 AirFrame *frame = *it; 00467 // time for the message to reach us 00468 double distance = myHostRef->pos.distance(frame->getSenderPos()); 00469 double propagationDelay = distance / LIGHT_SPEED; 00470 00471 // if this transmission is on our new channel and it would reach us in the future, then schedule it 00472 if (channel == frame->getChannelNumber()) 00473 { 00474 EV << " - (" << frame->className() << ")" << frame->name() << ": "; 00475 00476 // if there is a message on the air which will reach us in the future 00477 if (frame->timestamp() + propagationDelay >= simTime()) 00478 { 00479 EV << "will arrive in the future, scheduling it\n"; 00480 00481 // we need to send to each radioIn[] gate 00482 cGate *radioGate = gate("radioIn"); 00483 for (int i = 0; i < radioGate->size(); i++) 00484 sendDirect((cMessage*)frame->dup(), frame->timestamp() + propagationDelay - simTime(), this, radioGate->id() + i); 00485 } 00486 // if we hear some part of the message 00487 else if (frame->timestamp() + frame->getDuration() + propagationDelay > simTime()) 00488 { 00489 EV << "missed beginning of frame, processing it as noise\n"; 00490 00491 AirFrame *frameDup = (AirFrame*)frame->dup(); 00492 frameDup->setArrivalTime(frame->timestamp() + propagationDelay); 00493 handleLowerMsgStart(frameDup); 00494 bufferMsg(frameDup); 00495 } 00496 else 00497 { 00498 EV << "in the past\n"; 00499 } 00500 } 00501 } 00502 00503 // notify other modules about the channel switch; and actually, radio state has changed too 00504 nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); 00505 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00506 }
|
|
Redefined from BasicSnrEval Reimplemented from BasicSnrEval. 00099 {return rs.getChannelNumber();}
|
|
00087 { 00088 BasicSnrEval::finish(); 00089 }
|
|
00162 { 00163 if (msgkind==PHY_C_CONFIGURERADIO) 00164 { 00165 // extract new channel number 00166 PhyControlInfo *phyCtrl = check_and_cast<PhyControlInfo *>(ctrl); 00167 int newChannel = phyCtrl->channelNumber(); 00168 double newBitrate = phyCtrl->bitrate(); 00169 delete ctrl; 00170 00171 if (newChannel!=-1) 00172 { 00173 EV << "Command received: change to channel " << newChannel << "\n"; 00174 00175 // do it 00176 if (rs.getChannelNumber()==newChannel) 00177 EV << "Right on that channel, nothing to do\n"; // fine, nothing to do 00178 else if (rs.getState()==RadioState::TRANSMIT) { 00179 EV << "We're transmitting right now, remembering to change after it's completed\n"; 00180 this->newChannel = newChannel; 00181 } else 00182 changeChannel(newChannel); // change channel right now 00183 } 00184 if (newBitrate!=-1) 00185 { 00186 EV << "Command received: change bitrate to " << (newBitrate/1e6) << "Mbps\n"; 00187 00188 // do it 00189 if (rs.getBitrate()==newBitrate) 00190 EV << "Right at that bitrate, nothing to do\n"; // fine, nothing to do 00191 else if (rs.getState()==RadioState::TRANSMIT) { 00192 EV << "We're transmitting right now, remembering to change after it's completed\n"; 00193 this->newBitrate = newBitrate; 00194 } else 00195 setBitrate(newBitrate); // change bitrate right now 00196 } 00197 } 00198 else 00199 error("unknown command (msgkind=%d)", msgkind); 00200 }
|
|
Unbuffer the frame and update noise levels and snr information. This function is called right after the transmission is over, i.e. right after unbuffering. The noise level of the channel and the snr information of the buffered messages have to be updated. Additionally the RadioState has to be updated. If the corresponding AirFrame was not only noise the corresponding SnrList and the AirFrame are sent to the decider. Reimplemented from BasicSnrEval. Reimplemented in GilbertElliotSnr. 00347 { 00348 // check if message has to be send to the decider 00349 if (snrInfo.ptr == frame) 00350 { 00351 EV << "reception of frame over, preparing to send packet to upper layer\n"; 00352 // get Packet and list out of the receive buffer: 00353 SnrList list; 00354 list = snrInfo.sList; 00355 00356 // delete the pointer to indicate that no message is currently 00357 // being received and clear the list 00358 snrInfo.ptr = NULL; 00359 snrInfo.sList.clear(); 00360 00361 // delete the frame from the recvBuff 00362 recvBuff.erase(frame); 00363 00364 //Don't forget to send: 00365 sendUp(frame, list); 00366 EV << "packet sent to the decider\n"; 00367 } 00368 // all other messages are noise 00369 else 00370 { 00371 EV << "reception of noise message over, removing recvdPower from noiseLevel....\n"; 00372 // get the rcvdPower and subtract it from the noiseLevel 00373 noiseLevel -= recvBuff[frame]; 00374 00375 // delete message from the recvBuff 00376 recvBuff.erase(frame); 00377 00378 // update snr info for message currently being received if any 00379 if (snrInfo.ptr != NULL) 00380 { 00381 addNewSnr(); 00382 } 00383 00384 // message should be deleted 00385 delete frame; 00386 EV << "message deleted\n"; 00387 } 00388 00389 // check the RadioState and update if necessary 00390 // change to idle if noiseLevel smaller than threshold and state was 00391 // not idle before 00392 // do not change state if currently sending or receiving a message!!! 00393 if (noiseLevel < sensitivity && rs.getState() == RadioState::RECV && snrInfo.ptr == NULL) 00394 { 00395 // publish the new RadioState: 00396 EV << "new RadioState is IDLE\n"; 00397 rs.setState(RadioState::IDLE); 00398 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00399 } 00400 }
|
|
Buffer the frame and update noise levels and snr information. This function is called right after a packet arrived, i.e. right before it is buffered for 'transmission time'. First the receive power of the packet has to be calculated and is stored in the recvBuff. Afterwards it has to be decided whether the packet is just noise or a "real" packet that needs to be received. The message is not treated as noise if all of the following conditions apply:
If all conditions apply a new SnrList is created and the RadioState is changed to RECV. If the packet is just noise the receive power is added to the noise Level of the channel. Additionally the snr information of the currently being received message (if any) has to be updated as well as the RadioState. Reimplemented from BasicSnrEval. Reimplemented in GilbertElliotSnr. 00268 { 00269 // Calculate the receive power of the message 00270 00271 // calculate distance 00272 const Coord& myPos = myPosition(); 00273 const Coord& framePos = frame->getSenderPos(); 00274 double distance = myPos.distance(framePos); 00275 00276 // calculate receive power 00277 double rcvdPower = calcRcvdPower(frame->getPSend(), distance); 00278 00279 // store the receive power in the recvBuff 00280 recvBuff[frame] = rcvdPower; 00281 00282 // if receive power is bigger than sensitivity and if not sending 00283 // and currently not receiving another message and the message has 00284 // arrived in time 00285 // NOTE: a message may have arrival time in the past here when we are 00286 // processing ongoing transmissions during a channel change 00287 if (frame->arrivalTime() == simTime() && rcvdPower >= sensitivity && rs.getState() != RadioState::TRANSMIT && snrInfo.ptr == NULL) 00288 { 00289 EV << "receiving frame " << frame->name() << endl; 00290 00291 // Put frame and related SnrList in receive buffer 00292 SnrList snrList; //defined in SnrList.h!! 00293 snrInfo.ptr = frame; 00294 snrInfo.rcvdPower = rcvdPower; 00295 snrInfo.sList = snrList; 00296 00297 // add initial snr value 00298 addNewSnr(); 00299 00300 if (rs.getState() != RadioState::RECV) 00301 { 00302 // publish new RadioState 00303 rs.setState(RadioState::RECV); 00304 EV << "publish new RadioState:RECV\n"; 00305 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00306 } 00307 } 00308 // receive power is too low or another message is being sent or received 00309 else 00310 { 00311 EV << "frame " << frame->name() << " is just noise\n"; 00312 //add receive power to the noise level 00313 noiseLevel += rcvdPower; 00314 00315 // if a message is being received add a new snr value 00316 if (snrInfo.ptr != NULL) 00317 { 00318 // update snr info for currently being received message 00319 EV << "add new snr value to snr list of message being received\n"; 00320 addNewSnr(); 00321 } 00322 00323 // update the RadioState if the noiseLevel exceeded the threshold 00324 // and the radio is currently not in receive or in send mode 00325 if (noiseLevel >= sensitivity && rs.getState() == RadioState::IDLE) 00326 { 00327 // publish new RadioState 00328 rs.setState(RadioState::RECV); 00329 EV << "publish new RadioState:RECV\n"; 00330 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00331 } 00332 } 00333 }
|
|
Called every time a message arrives. The basic handle message function. Depending on the gate a message arrives handleMessage just calls different handle*Msg functions to further process the message. Messages from the channel are also buffered here in order to simulate a transmission delay You should not make any changes in this function but implement all your functionality into the handle*Msg functions called from here.
Reimplemented from BasicSnrEval. 00099 { 00100 if (msg->arrivalGateId()==uppergateIn && msg->length()==0) 00101 { 00102 cPolymorphic *ctrl = msg->removeControlInfo(); 00103 handleCommand(msg->kind(), ctrl); 00104 delete msg; 00105 } 00106 else 00107 { 00108 BasicSnrEval::handleMessage(msg); // let base class do it 00109 } 00110 }
|
|
The only self message that can arrive is a timer to indicate that sending of a message is completed. The RadioState has to be changed based on the noise level on the channel. If the noise level is bigger than the sensitivity switch to receive mode odtherwise to idle mode. Reimplemented from BasicSnrEval. Reimplemented in GilbertElliotSnr. 00211 { 00212 if (msg->kind() == TRANSM_OVER) 00213 { 00214 if (noiseLevel < sensitivity) 00215 { 00216 // set the RadioState to IDLE 00217 rs.setState(RadioState::IDLE); 00218 EV << "transmission over, switch to idle mode (state:IDLE)\n"; 00219 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00220 } 00221 else 00222 { 00223 // set the RadioState to RECV 00224 rs.setState(RadioState::RECV); 00225 EV << "transmission over but noise level too high, switch to recv mode (state:RECV)\n"; 00226 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00227 } 00228 00229 // delete the timer 00230 delete msg; 00231 00232 // switch channel if it needs be 00233 if (newChannel!=-1) 00234 { 00235 changeChannel(newChannel); 00236 newChannel = -1; 00237 } 00238 } 00239 else 00240 error("Internal error: unknown self-message `%s'", msg->name()); 00241 }
|
|
If a message is already being transmitted, an error is raised. Otherwise the RadioState is set to TRANSMIT and a timer is started. When this timer expires the RadioState will be set back to RECV (or IDLE respectively) again. If the host is receiving a packet this packet is from now on only considered as noise. Reimplemented from BasicSnrEval. 00123 { 00124 if (rs.getState() == RadioState::TRANSMIT) 00125 error("Trying to send a message while already transmitting -- MAC should " 00126 "take care this does not happen"); 00127 00128 if (frame->controlInfo()!=NULL) 00129 error("Setting control info (here: %s) on frames is not supported", frame->controlInfo()->className()); 00130 00131 // if a packet was being received, it is corrupted now as should be treated as noise 00132 if (snrInfo.ptr != NULL) 00133 { 00134 EV << "Sending a message while receiving another. The received one is now corrupted.\n"; 00135 00136 // remove the snr information stored for the message currently being 00137 // received. This message is treated as noise now and the 00138 // receive power has to be added to the noiseLevel 00139 00140 // delete the pointer to indicate that no message is being received 00141 snrInfo.ptr = NULL; 00142 // clear the snr list 00143 snrInfo.sList.clear(); 00144 // add the receive power to the noise level 00145 noiseLevel += snrInfo.rcvdPower; 00146 } 00147 00148 // now we are done with all the exception handling and can take care 00149 // about the "real" stuff 00150 00151 // change radio status 00152 rs.setState(RadioState::TRANSMIT); 00153 EV << "sending, changing RadioState to TRANSMIT\n"; 00154 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00155 00156 cMessage *timer = new cMessage(NULL, TRANSM_OVER); 00157 scheduleAt(simTime() + frame->getDuration(), timer); 00158 sendDown(frame); 00159 }
|
|
Initialize variables and publish the radio status.
Reimplemented from BasicSnrEval. Reimplemented in GilbertElliotSnr, and SnrEval80211. 00034 { 00035 BasicSnrEval::initialize(stage); 00036 00037 if (stage == 0) 00038 { 00039 // read parameters 00040 rs.setChannelNumber(par("channelNumber")); 00041 thermalNoise = FWMath::dBm2mW(par("thermalNoise")); 00042 carrierFrequency = cc->par("carrierFrequency"); // taken from ChannelControl 00043 sensitivity = FWMath::dBm2mW(par("sensitivity")); 00044 pathLossAlpha = par("pathLossAlpha"); 00045 if (pathLossAlpha < (double) (cc->par("alpha"))) 00046 error("SnrEval::initialize(): pathLossAlpha can't be smaller than in " 00047 "ChannelControl. Please adjust your omnetpp.ini file accordingly"); 00048 00049 // initialize noiseLevel 00050 noiseLevel = thermalNoise; 00051 00052 EV << "Initialized channel with noise: " << noiseLevel << " sensitivity: " << sensitivity << 00053 endl; 00054 00055 // initialize the pointer of the snrInfo with NULL to indicate 00056 // that currently no message is received 00057 snrInfo.ptr = NULL; 00058 00059 // no channel switch pending 00060 newChannel = -1; 00061 00062 // Initialize radio state. If thermal noise is already to high, radio 00063 // state has to be initialized as RECV 00064 rs.setState(RadioState::IDLE); 00065 if (noiseLevel >= sensitivity) 00066 rs.setState(RadioState::RECV); 00067 00068 WATCH(noiseLevel); 00069 WATCH(rs); 00070 } 00071 else if (stage == 1) 00072 { 00073 // tell initial value to MAC; must be done in stage 1, because they 00074 // subscribe in stage 0 00075 nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs); 00076 nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs); 00077 } 00078 else if (stage == 2) 00079 { 00080 // tell initial channel number to ChannelControl; should be done in 00081 // stage==2 or later, because base class initializes myHostRef in that stage 00082 cc->updateHostChannel(myHostRef, rs.getChannelNumber()); 00083 } 00084 }
|
|
change the bitrate to the given value. This method throws an error if the radio state is transmit.
00509 { 00510 if (this->bitrate == bitrate) 00511 return; 00512 if (bitrate < 0) 00513 error("setBitrate(): bitrate cannot be negative (%g)", bitrate); 00514 if (rs.getState() == RadioState::TRANSMIT) 00515 error("changing the bitrate while transmitting is not allowed"); 00516 00517 EV << "Setting bitrate to " << (bitrate/1e6) << "Mbps\n"; 00518 this->bitrate = bitrate; 00519 00520 //XXX fire some notification? 00521 }
|
|
Configuration: The carrier frequency used. It is read from the ChannelControl module.
|
|
State: if not -1, we have to switch to that bitrate once we finished transmitting.
|
|
State: if not -1, we have to switch to that channel once we finished transmitting.
|
|
State: the current noise level of the channel.
|
|
Configuration: Path loss coefficient. Can be specified in omnetpp.ini. If not it is read from the ChannelControl module. This value CANNOT be smaller than the one specified in the ChannelControl module, or the simulation will exit with an error!
|
|
State: A buffer to store a pointer to a message and the related receive power.
|
|
State: the current RadioState of the NIC; includes channel number.
|
|
Configuration: Defines up to what Power level (in dBm) a message can be understood. If the level of a received packet is lower, it is only treated as noise. Can be specified in omnetpp.ini. Default: -85 dBm.
|
|
State: SnrInfo stores the snrList and the the recvdPower for the message currently being received, together with a pointer to the message.
|
|
Configuration: Thermal noise on the channel. Can be specified in omnetpp.ini. Default: -100 dBm.
|