INET Framework for OMNeT++/OMNEST
AbstractRadio.cc
Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Andras Varga, Levente Meszaros
00003 // Based on the Mobility Framework's SnrEval by Marc Loebbers
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 
00020 #include "AbstractRadio.h"
00021 #include "FWMath.h"
00022 #include "PhyControlInfo_m.h"
00023 #include "Ieee80211Consts.h"  //XXX for the COLLISION and BITERROR msg kind constants
00024 
00025 
00026 #define MK_TRANSMISSION_OVER  1
00027 #define MK_RECEPTION_COMPLETE 2
00028 
00029 
00030 AbstractRadio::AbstractRadio() : rs(this->getId())
00031 {
00032     radioModel = NULL;
00033     receptionModel = NULL;
00034 }
00035 
00036 void AbstractRadio::initialize(int stage)
00037 {
00038     ChannelAccess::initialize(stage);
00039 
00040     EV << "Initializing AbstractRadio, stage=" << stage << endl;
00041 
00042     if (stage == 0)
00043     {
00044         gate("radioIn")->setDeliverOnReceptionStart(true);
00045 
00046         uppergateIn = findGate("uppergateIn");
00047         uppergateOut = findGate("uppergateOut");
00048 
00049         // read parameters
00050         transmitterPower = par("transmitterPower");
00051         if (transmitterPower > (double) (cc->par("pMax")))
00052             error("transmitterPower cannot be bigger than pMax in ChannelControl!");
00053         rs.setBitrate(par("bitrate"));
00054         rs.setChannelNumber(par("channelNumber"));
00055         thermalNoise = FWMath::dBm2mW(par("thermalNoise"));
00056         carrierFrequency = cc->par("carrierFrequency");  // taken from ChannelControl
00057         sensitivity = FWMath::dBm2mW(par("sensitivity"));
00058 
00059         // initialize noiseLevel
00060         noiseLevel = thermalNoise;
00061 
00062         EV << "Initialized channel with noise: " << noiseLevel << " sensitivity: " << sensitivity <<
00063             endl;
00064 
00065         // initialize the pointer of the snrInfo with NULL to indicate
00066         // that currently no message is received
00067         snrInfo.ptr = NULL;
00068 
00069         // no channel switch pending
00070         newChannel = -1;
00071 
00072         // Initialize radio state. If thermal noise is already to high, radio
00073         // state has to be initialized as RECV
00074         rs.setState(RadioState::IDLE);
00075         if (noiseLevel >= sensitivity)
00076             rs.setState(RadioState::RECV);
00077 
00078         WATCH(noiseLevel);
00079         WATCH(rs);
00080 
00081         receptionModel = createReceptionModel();
00082         receptionModel->initializeFrom(this);
00083 
00084         radioModel = createRadioModel();
00085         radioModel->initializeFrom(this);
00086     }
00087     else if (stage == 1)
00088     {
00089         // tell initial values to MAC; must be done in stage 1, because they
00090         // subscribe in stage 0
00091         nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs);
00092         nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs);
00093     }
00094     else if (stage == 2)
00095     {
00096         // tell initial channel number to ChannelControl; should be done in
00097         // stage==2 or later, because base class initializes myHostRef in that stage
00098         cc->updateHostChannel(myHostRef, rs.getChannelNumber());
00099     }
00100 }
00101 
00102 void AbstractRadio::finish()
00103 {
00104 }
00105 
00106 AbstractRadio::~AbstractRadio()
00107 {
00108     delete radioModel;
00109     delete receptionModel;
00110 
00111     // delete messages being received
00112     for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it)
00113         delete it->first;
00114 }
00115 
00131 void AbstractRadio::handleMessage(cMessage *msg)
00132 {
00133     // handle commands
00134     if (msg->getArrivalGateId()==uppergateIn && !msg->isPacket() /*FIXME XXX ENSURE REALLY PLAIN cMessage ARE SENT AS COMMANDS!!! && msg->getBitLength()==0*/)
00135     {
00136         cPolymorphic *ctrl = msg->removeControlInfo();
00137         if (msg->getKind()==0)
00138             error("Message '%s' with length==0 is supposed to be a command, but msg kind is also zero", msg->getName());
00139         handleCommand(msg->getKind(), ctrl);
00140         delete msg;
00141         return;
00142     }
00143 
00144     if (msg->getArrivalGateId() == uppergateIn)
00145     {
00146         AirFrame *airframe = encapsulatePacket(PK(msg));
00147         handleUpperMsg(airframe);
00148     }
00149     else if (msg->isSelfMessage())
00150     {
00151         handleSelfMsg(msg);
00152     }
00153     else if (check_and_cast<AirFrame *>(msg)->getChannelNumber() == getChannelNumber())
00154     {
00155         // must be an AirFrame
00156         AirFrame *airframe = (AirFrame *) msg;
00157         handleLowerMsgStart(airframe);
00158         bufferMsg(airframe);
00159     }
00160     else
00161     {
00162         EV << "listening to different channel when receiving message -- dropping it\n";
00163         delete msg;
00164     }
00165 }
00166 
00173 void AbstractRadio::bufferMsg(AirFrame *airframe) //FIXME: add explicit simtime_t atTime arg?
00174 {
00175     // set timer to indicate transmission is complete
00176     cMessage *endRxTimer = new cMessage("endRx", MK_RECEPTION_COMPLETE);
00177     endRxTimer->setContextPointer(airframe);
00178     airframe->setContextPointer(endRxTimer);
00179 
00180     // NOTE: use arrivalTime instead of simTime, because we might be calling this
00181     // function during a channel change, when we're picking up ongoing transmissions
00182     // on the channel -- and then the message's arrival time is in the past!
00183     scheduleAt(airframe->getArrivalTime() + airframe->getDuration(), endRxTimer);
00184 }
00185 
00186 AirFrame *AbstractRadio::encapsulatePacket(cPacket *frame)
00187 {
00188     PhyControlInfo *ctrl = dynamic_cast<PhyControlInfo *>(frame->removeControlInfo());
00189     ASSERT(!ctrl || ctrl->getChannelNumber()==-1); // per-packet channel switching not supported
00190 
00191     // Note: we don't set length() of the AirFrame, because duration will be used everywhere instead
00192     AirFrame *airframe = createAirFrame();
00193     airframe->setName(frame->getName());
00194     airframe->setPSend(transmitterPower);
00195     airframe->setChannelNumber(getChannelNumber());
00196     airframe->encapsulate(frame);
00197     airframe->setBitrate(ctrl ? ctrl->getBitrate() : rs.getBitrate());
00198     airframe->setDuration(radioModel->calculateDuration(airframe));
00199     airframe->setSenderPos(getMyPosition());
00200     delete ctrl;
00201 
00202     EV << "Frame (" << frame->getClassName() << ")" << frame->getName()
00203        << " will be transmitted at " << (airframe->getBitrate()/1e6) << "Mbps\n";
00204     return airframe;
00205 }
00206 
00207 void AbstractRadio::sendUp(AirFrame *airframe)
00208 {
00209     cPacket *frame = airframe->decapsulate();
00210     delete airframe;
00211     EV << "sending up frame " << frame->getName() << endl;
00212     send(frame, uppergateOut);
00213 }
00214 
00215 void AbstractRadio::sendDown(AirFrame *airframe)
00216 {
00217     sendToChannel(airframe);
00218 }
00219 
00224 AirFrame *AbstractRadio::unbufferMsg(cMessage *msg)
00225 {
00226     AirFrame *airframe = (AirFrame *) msg->getContextPointer();
00227     //delete the self message
00228     delete msg;
00229 
00230     return airframe;
00231 }
00232 
00243 void AbstractRadio::handleUpperMsg(AirFrame *airframe)
00244 {
00245     if (rs.getState() == RadioState::TRANSMIT)
00246         error("Trying to send a message while already transmitting -- MAC should "
00247               "take care this does not happen");
00248 
00249     // if a packet was being received, it is corrupted now as should be treated as noise
00250     if (snrInfo.ptr != NULL)
00251     {
00252         EV << "Sending a message while receiving another. The received one is now corrupted.\n";
00253 
00254         // remove the snr information stored for the message currently being
00255         // received. This message is treated as noise now and the
00256         // receive power has to be added to the noiseLevel
00257 
00258         // delete the pointer to indicate that no message is being received
00259         snrInfo.ptr = NULL;
00260         // clear the snr list
00261         snrInfo.sList.clear();
00262         // add the receive power to the noise level
00263         noiseLevel += snrInfo.rcvdPower;
00264     }
00265 
00266     // now we are done with all the exception handling and can take care
00267     // about the "real" stuff
00268 
00269     // change radio status
00270     EV << "sending, changing RadioState to TRANSMIT\n";
00271     setRadioState(RadioState::TRANSMIT);
00272 
00273     cMessage *timer = new cMessage(NULL, MK_TRANSMISSION_OVER);
00274     scheduleAt(simTime() + airframe->getDuration(), timer);
00275     sendDown(airframe);
00276 }
00277 
00278 void AbstractRadio::handleCommand(int msgkind, cPolymorphic *ctrl)
00279 {
00280     if (msgkind==PHY_C_CONFIGURERADIO)
00281     {
00282         // extract new channel number
00283         PhyControlInfo *phyCtrl = check_and_cast<PhyControlInfo *>(ctrl);
00284         int newChannel = phyCtrl->getChannelNumber();
00285         double newBitrate = phyCtrl->getBitrate();
00286         delete ctrl;
00287 
00288         if (newChannel!=-1)
00289         {
00290             EV << "Command received: change to channel #" << newChannel << "\n";
00291 
00292             // do it
00293             if (rs.getChannelNumber()==newChannel)
00294                 EV << "Right on that channel, nothing to do\n"; // fine, nothing to do
00295             else if (rs.getState()==RadioState::TRANSMIT) {
00296                 EV << "We're transmitting right now, remembering to change after it's completed\n";
00297                 this->newChannel = newChannel;
00298             } else
00299                 changeChannel(newChannel); // change channel right now
00300         }
00301         if (newBitrate!=-1)
00302         {
00303             EV << "Command received: change bitrate to " << (newBitrate/1e6) << "Mbps\n";
00304 
00305             // do it
00306             if (rs.getBitrate()==newBitrate)
00307                 EV << "Right at that bitrate, nothing to do\n"; // fine, nothing to do
00308             else if (rs.getState()==RadioState::TRANSMIT) {
00309                 EV << "We're transmitting right now, remembering to change after it's completed\n";
00310                 this->newBitrate = newBitrate;
00311             } else
00312                 setBitrate(newBitrate); // change bitrate right now
00313         }
00314     }
00315     else
00316     {
00317         error("unknown command (msgkind=%d)", msgkind);
00318     }
00319 }
00320 
00321 void AbstractRadio::handleSelfMsg(cMessage *msg)
00322 {
00323     if (msg->getKind()==MK_RECEPTION_COMPLETE)
00324     {
00325         EV << "frame is completely received now\n";
00326 
00327         // unbuffer the message
00328         AirFrame *airframe = unbufferMsg(msg);
00329 
00330         handleLowerMsgEnd(airframe);
00331     }
00332     else if (msg->getKind() == MK_TRANSMISSION_OVER)
00333     {
00334         // Transmission has completed. The RadioState has to be changed
00335         // to IDLE or RECV, based on the noise level on the channel.
00336         // If the noise level is bigger than the sensitivity switch to receive mode,
00337         // otherwise to idle mode.
00338         if (noiseLevel < sensitivity)
00339         {
00340             // set the RadioState to IDLE
00341             EV << "transmission over, switch to idle mode (state:IDLE)\n";
00342             setRadioState(RadioState::IDLE);
00343         }
00344         else
00345         {
00346             // set the RadioState to RECV
00347             EV << "transmission over but noise level too high, switch to recv mode (state:RECV)\n";
00348             setRadioState(RadioState::RECV);
00349         }
00350 
00351         // delete the timer
00352         delete msg;
00353 
00354         // switch channel if it needs be
00355         if (newChannel!=-1)
00356         {
00357             changeChannel(newChannel);
00358             newChannel = -1;
00359         }
00360     }
00361     else
00362     {
00363         error("Internal error: unknown self-message `%s'", msg->getName());
00364     }
00365 }
00366 
00367 
00391 void AbstractRadio::handleLowerMsgStart(AirFrame * airframe)
00392 {
00393     // Calculate the receive power of the message
00394 
00395     // calculate distance
00396     const Coord& myPos = getMyPosition();
00397     const Coord& framePos = airframe->getSenderPos();
00398     double distance = myPos.distance(framePos);
00399 
00400     // calculate receive power
00401     double rcvdPower = receptionModel->calculateReceivedPower(airframe->getPSend(), carrierFrequency, distance);
00402 
00403     // store the receive power in the recvBuff
00404     recvBuff[airframe] = rcvdPower;
00405 
00406     // if receive power is bigger than sensitivity and if not sending
00407     // and currently not receiving another message and the message has
00408     // arrived in time
00409     // NOTE: a message may have arrival time in the past here when we are
00410     // processing ongoing transmissions during a channel change
00411     if (airframe->getArrivalTime() == simTime() && rcvdPower >= sensitivity && rs.getState() != RadioState::TRANSMIT && snrInfo.ptr == NULL)
00412     {
00413         EV << "receiving frame " << airframe->getName() << endl;
00414 
00415         // Put frame and related SnrList in receive buffer
00416         SnrList snrList;
00417         snrInfo.ptr = airframe;
00418         snrInfo.rcvdPower = rcvdPower;
00419         snrInfo.sList = snrList;
00420 
00421         // add initial snr value
00422         addNewSnr();
00423 
00424         if (rs.getState() != RadioState::RECV)
00425         {
00426             // publish new RadioState
00427             EV << "publish new RadioState:RECV\n";
00428             setRadioState(RadioState::RECV);
00429         }
00430     }
00431     // receive power is too low or another message is being sent or received
00432     else
00433     {
00434         EV << "frame " << airframe->getName() << " is just noise\n";
00435         //add receive power to the noise level
00436         noiseLevel += rcvdPower;
00437 
00438         // if a message is being received add a new snr value
00439         if (snrInfo.ptr != NULL)
00440         {
00441             // update snr info for currently being received message
00442             EV << "adding new snr value to snr list of message being received\n";
00443             addNewSnr();
00444         }
00445 
00446         // update the RadioState if the noiseLevel exceeded the threshold
00447         // and the radio is currently not in receive or in send mode
00448         if (noiseLevel >= sensitivity && rs.getState() == RadioState::IDLE)
00449         {
00450             EV << "setting radio state to RECV\n";
00451             setRadioState(RadioState::RECV);
00452         }
00453     }
00454 }
00455 
00456 
00467 void AbstractRadio::handleLowerMsgEnd(AirFrame * airframe)
00468 {
00469     // check if message has to be send to the decider
00470     if (snrInfo.ptr == airframe)
00471     {
00472         EV << "reception of frame over, preparing to send packet to upper layer\n";
00473         // get Packet and list out of the receive buffer:
00474         SnrList list;
00475         list = snrInfo.sList;
00476 
00477         // delete the pointer to indicate that no message is currently
00478         // being received and clear the list
00479         snrInfo.ptr = NULL;
00480         snrInfo.sList.clear();
00481 
00482         // delete the frame from the recvBuff
00483         recvBuff.erase(airframe);
00484 
00485         //XXX send up the frame:
00486         //if (radioModel->isReceivedCorrectly(airframe, list))
00487         //    sendUp(airframe);
00488         //else
00489         //    delete airframe;
00490         if (!radioModel->isReceivedCorrectly(airframe, list))
00491         {
00492             airframe->getEncapsulatedPacket()->setKind(list.size()>1 ? COLLISION : BITERROR);
00493             airframe->setName(list.size()>1 ? "COLLISION" : "BITERROR");
00494         }
00495         sendUp(airframe);
00496     }
00497     // all other messages are noise
00498     else
00499     {
00500         EV << "reception of noise message over, removing recvdPower from noiseLevel....\n";
00501         // get the rcvdPower and subtract it from the noiseLevel
00502         noiseLevel -= recvBuff[airframe];
00503 
00504         // delete message from the recvBuff
00505         recvBuff.erase(airframe);
00506 
00507         // update snr info for message currently being received if any
00508         if (snrInfo.ptr != NULL)
00509         {
00510             addNewSnr();
00511         }
00512 
00513         // message should be deleted
00514         delete airframe;
00515         EV << "message deleted\n";
00516     }
00517 
00518     // check the RadioState and update if necessary
00519     // change to idle if noiseLevel smaller than threshold and state was
00520     // not idle before
00521     // do not change state if currently sending or receiving a message!!!
00522     if (noiseLevel < sensitivity && rs.getState() == RadioState::RECV && snrInfo.ptr == NULL)
00523     {
00524         // publish the new RadioState:
00525         EV << "new RadioState is IDLE\n";
00526         setRadioState(RadioState::IDLE);
00527     }
00528 }
00529 
00530 void AbstractRadio::addNewSnr()
00531 {
00532     SnrListEntry listEntry;     // create a new entry
00533     listEntry.time = simTime();
00534     listEntry.snr = snrInfo.rcvdPower / noiseLevel;
00535     snrInfo.sList.push_back(listEntry);
00536 }
00537 
00538 void AbstractRadio::changeChannel(int channel)
00539 {
00540     if (channel == rs.getChannelNumber())
00541         return;
00542     if (channel < 0 || channel >= cc->getNumChannels())
00543         error("changeChannel(): channel number %d is out of range (hint: numChannels is a parameter of ChannelControl)", channel);
00544     if (rs.getState() == RadioState::TRANSMIT)
00545         error("changing channel while transmitting is not allowed");
00546 
00547     // if we are currently receiving, must clean that up before moving to different channel
00548     if (rs.getState() == RadioState::RECV)
00549     {
00550         // delete messages being received, and cancel associated self-messages
00551         for (RecvBuff::iterator it = recvBuff.begin(); it!=recvBuff.end(); ++it)
00552         {
00553             AirFrame *airframe = it->first;
00554             cMessage *endRxTimer = (cMessage *)airframe->getContextPointer();
00555             delete airframe;
00556             delete cancelEvent(endRxTimer);
00557         }
00558         recvBuff.clear();
00559     }
00560 
00561     // clear snr info
00562     snrInfo.ptr = NULL;
00563     snrInfo.sList.clear();
00564 
00565     // do channel switch
00566     EV << "Changing to channel #" << channel << "\n";
00567 
00568     rs.setChannelNumber(channel);
00569     cc->updateHostChannel(myHostRef, channel);
00570     ChannelControl::TransmissionList tl = cc->getOngoingTransmissions(channel);
00571 
00572     cModule *myHost = findHost();
00573     cGate *radioGate = myHost->gate("radioIn");
00574 
00575     // pick up ongoing transmissions on the new channel
00576     EV << "Picking up ongoing transmissions on new channel:\n";
00577     for (ChannelControl::TransmissionList::const_iterator it = tl.begin(); it != tl.end(); ++it)
00578     {
00579         AirFrame *airframe = *it;
00580         // time for the message to reach us
00581         double distance = myHostRef->pos.distance(airframe->getSenderPos());
00582         simtime_t propagationDelay = distance / LIGHT_SPEED;
00583 
00584         // if this transmission is on our new channel and it would reach us in the future, then schedule it
00585         if (channel == airframe->getChannelNumber())
00586         {
00587             EV << " - (" << airframe->getClassName() << ")" << airframe->getName() << ": ";
00588 
00589             // if there is a message on the air which will reach us in the future
00590             if (airframe->getTimestamp() + propagationDelay >= simTime())
00591             {
00592                  EV << "will arrive in the future, scheduling it\n";
00593 
00594                  // we need to send to each radioIn[] gate of this host
00595                  for (int i = 0; i < radioGate->size(); i++)
00596                      sendDirect(airframe->dup(), airframe->getTimestamp() + propagationDelay - simTime(), airframe->getDuration(), myHost, radioGate->getId() + i);
00597             }
00598             // if we hear some part of the message
00599             else if (airframe->getTimestamp() + airframe->getDuration() + propagationDelay > simTime())
00600             {
00601                  EV << "missed beginning of frame, processing it as noise\n";
00602 
00603                  AirFrame *frameDup = airframe->dup();
00604                  frameDup->setArrivalTime(airframe->getTimestamp() + propagationDelay);
00605                  handleLowerMsgStart(frameDup);
00606                  bufferMsg(frameDup);
00607             }
00608             else
00609             {
00610                 EV << "in the past\n";
00611             }
00612         }
00613     }
00614 
00615     // notify other modules about the channel switch; and actually, radio state has changed too
00616     nb->fireChangeNotification(NF_RADIO_CHANNEL_CHANGED, &rs);
00617     nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs);
00618 }
00619 
00620 void AbstractRadio::setBitrate(double bitrate)
00621 {
00622     if (rs.getBitrate() == bitrate)
00623         return;
00624     if (bitrate < 0)
00625         error("setBitrate(): bitrate cannot be negative (%g)", bitrate);
00626     if (rs.getState() == RadioState::TRANSMIT)
00627         error("changing the bitrate while transmitting is not allowed");
00628 
00629     EV << "Setting bitrate to " << (bitrate/1e6) << "Mbps\n";
00630     rs.setBitrate(bitrate);
00631 
00632     //XXX fire some notification?
00633 }
00634 
00635 void AbstractRadio::setRadioState(RadioState::State newState)
00636 {
00637     rs.setState(newState);
00638     nb->fireChangeNotification(NF_RADIOSTATE_CHANGED, &rs);
00639 }
00640