BasePhyLayer.cc

00001 #include "BasePhyLayer.h"
00002 #include "BaseWorldUtility.h"
00003 
00004 #include "MacToPhyControlInfo.h"
00005 #include "PhyToMacControlInfo.h"
00006 
00007 
00008 
00009 //introduce BasePhyLayer as module to OMNet
00010 Define_Module(BasePhyLayer);
00011 
00012 short BasePhyLayer::airFramePriority = 10;
00013 
00014 //--Initialization----------------------------------
00015 
00016 BasePhyLayer::BasePhyLayer():
00017   protocolId(GENERIC),
00018   thermalNoise(0),
00019   radio(0),
00020   decider(0),
00021   radioSwitchingOverTimer(0),
00022   txOverTimer(0),
00023   world(0)
00024 {}
00025 
00026 template<class T> T BasePhyLayer::readPar(const char* parName, const T defaultValue){
00027   if(hasPar(parName))
00028     return par(parName);
00029   else
00030     return defaultValue;
00031 }
00032 
00033 // the following line is needed to allow linking when compiled in RELEASE mode.
00034 // Add a declaration for each parameterization of the template used in
00035 // code to be linked, e.g. in modules or in examples, if it is not already
00036 // used in base (double and simtime_t). Needed with (at least): gcc 4.4.1.
00037 template int BasePhyLayer::readPar<int>(const char* parName, const int);
00038 template double BasePhyLayer::readPar<double>(const char* parName, const double);
00039 template simtime_t BasePhyLayer::readPar<simtime_t>(const char* parName, const simtime_t);
00040 template bool BasePhyLayer::readPar<bool>(const char* parName, const bool);
00041 
00042 void BasePhyLayer::initialize(int stage) {
00043 
00044   ChannelAccess::initialize(stage);
00045 
00046   if (stage == 0) {
00047     // if using sendDirect, make sure that messages arrive without delay
00048     gate("radioIn")->setDeliverOnReceptionStart(true);
00049 
00050     //get gate ids
00051     upperGateIn = findGate("upperGateIn");
00052         upperGateOut = findGate("upperGateOut");
00053         upperControlOut = findGate("upperControlOut");
00054         upperControlIn = findGate("upperControlIn");
00055 
00056     //read simple ned-parameters
00057     //  - initialize basic parameters
00058         if(par("useThermalNoise").boolValue()) {
00059       double thermalNoiseVal = FWMath::dBm2mW(par("thermalNoise").doubleValue());
00060       thermalNoise = new ConstantSimpleConstMapping(DimensionSet::timeDomain,
00061                               thermalNoiseVal);
00062     } else {
00063       thermalNoise = 0;
00064     }
00065         headerLength = par("headerLength").longValue();
00066     sensitivity = par("sensitivity").doubleValue();
00067     sensitivity = FWMath::dBm2mW(sensitivity);
00068     maxTXPower = par("maxTXPower").doubleValue();
00069 
00070     recordStats = par("recordStats").boolValue();
00071 
00072     //  - initialize radio
00073     radio = initializeRadio();
00074 
00075     // get pointer to the world module
00076     world = FindModule<BaseWorldUtility*>::findGlobalModule();
00077         if (world == NULL) {
00078             opp_error("Could not find BaseWorldUtility module");
00079         }
00080 
00081         if(cc->hasPar("sat")
00082        && (sensitivity - FWMath::dBm2mW(cc->par("sat").doubleValue())) < -0.000001) {
00083             opp_error("Sensitivity can't be smaller than the "
00084             "signal attenuation threshold (sat) in ConnectionManager. "
00085             "Please adjust your omnetpp.ini file accordingly.");
00086     }
00087 
00088 //  } else if (stage == 1){
00089     //read complex(xml) ned-parameters
00090     //  - analogue model parameters
00091     initializeAnalogueModels(par("analogueModels").xmlValue());
00092     //  - decider parameters
00093     initializeDecider(par("decider").xmlValue());
00094 
00095     //initialise timer messages
00096     radioSwitchingOverTimer = new cMessage("radio switching over", RADIO_SWITCHING_OVER);
00097     txOverTimer = new cMessage("transmission over", TX_OVER);
00098 
00099   }
00100 }
00101 
00102 Radio* BasePhyLayer::initializeRadio() {
00103   int initialRadioState = par("initialRadioState").longValue();
00104   double radioMinAtt = par("radioMinAtt").doubleValue();
00105   double radioMaxAtt = par("radioMaxAtt").doubleValue();
00106   int nbRadioChannels = readPar("nbRadioChannels", 1);
00107   int initialRadioChannel = readPar("initialRadioChannel", 0);
00108 
00109   Radio* radio = Radio::createNewRadio(recordStats, initialRadioState,
00110                      radioMinAtt, radioMaxAtt,
00111                      initialRadioChannel, nbRadioChannels);
00112 
00113   //  - switch times to TX
00114   simtime_t rxToTX = par("timeRXToTX").doubleValue();
00115   simtime_t sleepToTX = par("timeSleepToTX").doubleValue();
00116 
00117   //if no RX to TX defined asume same time as sleep to TX
00118   radio->setSwitchTime(Radio::RX, Radio::TX, par("timeRXToTX").doubleValue());
00119   //if no sleep to TX defined asume same time as RX to TX
00120   radio->setSwitchTime(Radio::SLEEP, Radio::TX, par("timeSleepToTX").doubleValue());
00121 
00122 
00123   //    - switch times to RX
00124   simtime_t txToRX = par("timeTXToRX").doubleValue();
00125   simtime_t sleepToRX = par("timeSleepToRX").doubleValue();
00126 
00127   //if no TX to RX defined asume same time as sleep to RX
00128   radio->setSwitchTime(Radio::TX, Radio::RX, par("timeTXToRX").doubleValue());
00129   //if no sleep to RX defined asume same time as TX to RX
00130   radio->setSwitchTime(Radio::SLEEP, Radio::RX, par("timeSleepToRX").doubleValue());
00131 
00132 
00133   //    - switch times to sleep
00134   simtime_t txToSleep = par("timeTXToSleep").doubleValue();
00135   simtime_t rxToSleep = par("timeRXToSleep").doubleValue();
00136 
00137   //if no TX to sleep defined asume same time as RX to sleep
00138   radio->setSwitchTime(Radio::TX, Radio::SLEEP, par("timeTXToSleep").doubleValue());
00139   //if no RX to sleep defined asume same time as TX to sleep
00140   radio->setSwitchTime(Radio::RX, Radio::SLEEP, par("timeRXToSleep").doubleValue());
00141 
00142   return radio;
00143 }
00144 
00145 void BasePhyLayer::getParametersFromXML(cXMLElement* xmlData, ParameterMap& outputMap) {
00146   cXMLElementList parameters = xmlData->getElementsByTagName("Parameter");
00147 
00148   for(cXMLElementList::const_iterator it = parameters.begin();
00149     it != parameters.end(); it++) {
00150 
00151     const char* name = (*it)->getAttribute("name");
00152     const char* type = (*it)->getAttribute("type");
00153     const char* value = (*it)->getAttribute("value");
00154     if(name == 0 || type == 0 || value == 0) {
00155       ev << "Invalid parameter, could not find name, type or value." << endl;
00156       continue;
00157     }
00158 
00159     std::string sType = type;   //needed for easier comparision
00160     std::string sValue = value; //needed for easier comparision
00161 
00162     cMsgPar param(name);
00163 
00164     //parse type of parameter and set value
00165     if (sType == "bool") {
00166       param.setBoolValue(sValue == "true" || sValue == "1");
00167 
00168     } else if (sType == "double") {
00169       param.setDoubleValue(strtod(value, 0));
00170 
00171     } else if (sType == "string") {
00172       param.setStringValue(value);
00173 
00174     } else if (sType == "long") {
00175       param.setLongValue(strtol(value, 0, 0));
00176 
00177     } else {
00178       ev << "Unknown parameter type: \"" << sType << "\"" << endl;
00179       continue;
00180     }
00181 
00182     //add parameter to output map
00183     outputMap[name] = param;
00184   }
00185 }
00186 
00187 void BasePhyLayer::finish(){
00188   // give decider the chance to do something
00189   decider->finish();
00190 }
00191 
00192 //-----Decider initialization----------------------
00193 
00194 
00195 void BasePhyLayer::initializeDecider(cXMLElement* xmlConfig) {
00196 
00197   decider = 0;
00198 
00199   if(xmlConfig == 0) {
00200     opp_error("No decider configuration file specified.");
00201     return;
00202   }
00203 
00204   cXMLElementList deciderList = xmlConfig->getElementsByTagName("Decider");
00205 
00206   if(deciderList.empty()) {
00207     opp_error("No decider configuration found in configuration file.");
00208     return;
00209   }
00210 
00211   if(deciderList.size() > 1) {
00212     opp_error("More than one decider configuration found in configuration file.");
00213     return;
00214   }
00215 
00216   cXMLElement* deciderData = deciderList.front();
00217 
00218   const char* name = deciderData->getAttribute("type");
00219 
00220   if(name == 0) {
00221     opp_error("Could not read type of decider from configuration file.");
00222     return;
00223   }
00224 
00225   ParameterMap params;
00226   getParametersFromXML(deciderData, params);
00227 
00228   decider = getDeciderFromName(name, params);
00229 
00230   if(decider == 0) {
00231     opp_error("Could not find a decider with the name \"%s\".", name);
00232     return;
00233   }
00234 
00235   coreEV << "Decider \"" << name << "\" loaded." << endl;
00236 }
00237 
00238 Decider* BasePhyLayer::getDeciderFromName(std::string name, ParameterMap& params)
00239 {
00240 
00241   return 0;
00242 }
00243 
00244 
00245 //-----AnalogueModels initialization----------------
00246 
00247 void BasePhyLayer::initializeAnalogueModels(cXMLElement* xmlConfig) {
00248 
00249   /*
00250   * first of all, attach the AnalogueModel that represents the RadioState
00251   * to the AnalogueModelList as first element.
00252   */
00253 
00254   std::string s("RadioStateAnalogueModel");
00255   ParameterMap p;
00256 
00257   AnalogueModel* newAnalogueModel = getAnalogueModelFromName(s, p);
00258 
00259   if(newAnalogueModel == 0)
00260   {
00261     opp_warning("Could not find an analogue model with the name \"%s\".", s.c_str());
00262   }
00263   else
00264   {
00265     analogueModels.push_back(newAnalogueModel);
00266   }
00267 
00268 
00269   if(xmlConfig == 0) {
00270     opp_warning("No analogue models configuration file specified.");
00271     return;
00272   }
00273 
00274   cXMLElementList analogueModelList = xmlConfig->getElementsByTagName("AnalogueModel");
00275 
00276   if(analogueModelList.empty()) {
00277     opp_warning("No analogue models configuration found in configuration file.");
00278     return;
00279   }
00280 
00281   // iterate over all AnalogueModel-entries, get a new AnalogueModel instance and add
00282   // it to analogueModels
00283   for(cXMLElementList::const_iterator it = analogueModelList.begin();
00284     it != analogueModelList.end(); it++) {
00285 
00286 
00287     cXMLElement* analogueModelData = *it;
00288 
00289     const char* name = analogueModelData->getAttribute("type");
00290 
00291     if(name == 0) {
00292       opp_warning("Could not read name of analogue model.");
00293       continue;
00294     }
00295 
00296     ParameterMap params;
00297     getParametersFromXML(analogueModelData, params);
00298 
00299     AnalogueModel* newAnalogueModel = getAnalogueModelFromName(name, params);
00300 
00301     if(newAnalogueModel == 0) {
00302       opp_warning("Could not find an analogue model with the name \"%s\".", name);
00303       continue;
00304     }
00305 
00306     // attach the new AnalogueModel to the AnalogueModelList
00307     analogueModels.push_back(newAnalogueModel);
00308 
00309     coreEV << "AnalogueModel \"" << name << "\" loaded." << endl;
00310 
00311   } // end iterator loop
00312 
00313 
00314 }
00315 
00316 AnalogueModel* BasePhyLayer::getAnalogueModelFromName(std::string name, ParameterMap& params) {
00317 
00318   // add default analogue models here
00319 
00320   // case "RSAM", pointer is valid as long as the radio exists
00321   if (name == "RadioStateAnalogueModel")
00322   {
00323     return radio->getAnalogueModel();
00324   }
00325 
00326   return 0;
00327 }
00328 
00329 
00330 
00331 //--Message handling--------------------------------------
00332 
00333 void BasePhyLayer::handleMessage(cMessage* msg) {
00334 
00335   //self messages
00336   if(msg->isSelfMessage()) {
00337     handleSelfMessage(msg);
00338 
00339   //MacPkts <- MacToPhyControlInfo
00340   } else if(msg->getArrivalGateId() == upperGateIn) {
00341     handleUpperMessage(msg);
00342 
00343   //controlmessages
00344   } else if(msg->getArrivalGateId() == upperControlIn) {
00345     handleUpperControlMessage(msg);
00346 
00347   //AirFrames
00348   } else if(msg->getKind() == AIR_FRAME){
00349     handleAirFrame(msg);
00350 
00351   //unknown message
00352   } else {
00353     ev << "Unknown message received." << endl;
00354     delete msg;
00355   }
00356 }
00357 
00358 void BasePhyLayer::handleAirFrame(cMessage* msg) {
00359   AirFrame* frame = static_cast<AirFrame*>(msg);
00360 
00361   //TODO: ask jerome to set air frame priority in his UWBIRPhy
00362   //assert(frame->getSchedulingPriority() == airFramePriority);
00363 
00364   switch(frame->getState()) {
00365   case START_RECEIVE:
00366     handleAirFrameStartReceive(frame);
00367     break;
00368 
00369   case RECEIVING: {
00370     handleAirFrameReceiving(frame);
00371     break;
00372   }
00373   case END_RECEIVE:
00374     handleAirFrameEndReceive(frame);
00375     break;
00376 
00377   default:
00378     opp_error( "Unknown AirFrame state: %s", frame->getState());
00379     break;
00380   }
00381 }
00382 
00383 void BasePhyLayer::handleAirFrameStartReceive(AirFrame* frame) {
00384   coreEV << "Received new AirFrame " << frame << " from channel." << endl;
00385 
00386   if(channelInfo.isChannelEmpty()) {
00387     radio->setTrackingModeTo(true);
00388   }
00389 
00390   channelInfo.addAirFrame(frame, simTime());
00391   assert(!channelInfo.isChannelEmpty());
00392 
00393   if(usePropagationDelay) {
00394     Signal& s = frame->getSignal();
00395     simtime_t delay = simTime() - s.getSignalStart();
00396     s.setPropagationDelay(delay);
00397   }
00398   assert(frame->getSignal().getSignalStart() == simTime());
00399 
00400   filterSignal(frame->getSignal());
00401 
00402   if(decider and isKnownProtocolId(frame->getProtocolId())) {
00403     frame->setState(RECEIVING);
00404 
00405     //pass the AirFrame the first time to the Decider
00406     handleAirFrameReceiving(frame);
00407 
00408   //if no decider is defined we will schedule the message directly to its end
00409   } else {
00410     Signal& signal = frame->getSignal();
00411 
00412     simtime_t signalEndTime = signal.getSignalStart() + frame->getDuration();
00413     frame->setState(END_RECEIVE);
00414 
00415     sendSelfMessage(frame, signalEndTime);
00416   }
00417 }
00418 
00419 void BasePhyLayer::handleAirFrameReceiving(AirFrame* frame) {
00420 
00421   Signal& signal = frame->getSignal();
00422   simtime_t nextHandleTime = decider->processSignal(frame);
00423 
00424   assert(signal.getSignalLength() == frame->getDuration());
00425   simtime_t signalEndTime = signal.getSignalStart() + frame->getDuration();
00426 
00427   //check if this is the end of the receiving process
00428   if(simTime() >= signalEndTime) {
00429     frame->setState(END_RECEIVE);
00430     handleAirFrameEndReceive(frame);
00431     return;
00432   }
00433 
00434   //smaller zero means don't give it to me again
00435   if(nextHandleTime < 0) {
00436     nextHandleTime = signalEndTime;
00437     frame->setState(END_RECEIVE);
00438 
00439   //invalid point in time
00440   } else if(nextHandleTime < simTime() || nextHandleTime > signalEndTime) {
00441     opp_error("Invalid next handle time returned by Decider. Expected a value between current simulation time (%.2f) and end of signal (%.2f) but got %.2f",
00442                 SIMTIME_DBL(simTime()), SIMTIME_DBL(signalEndTime), SIMTIME_DBL(nextHandleTime));
00443   }
00444 
00445   coreEV << "Handed AirFrame with ID " << frame->getId() << " to Decider. Next handling in " << nextHandleTime - simTime() << "s." << endl;
00446 
00447   sendSelfMessage(frame, nextHandleTime);
00448 }
00449 
00450 void BasePhyLayer::handleAirFrameEndReceive(AirFrame* frame) {
00451   coreEV << "End of Airframe with ID " << frame->getId() << "." << endl;
00452 
00453   simtime_t earliestInfoPoint = channelInfo.removeAirFrame(frame);
00454 
00455   /* clean information in the radio until earliest time-point
00456   *  of information in the ChannelInfo,
00457   *  since this time-point might have changed due to removal of
00458   *  the AirFrame
00459   */
00460   if(channelInfo.isChannelEmpty()) {
00461     earliestInfoPoint = simTime();
00462     radio->setTrackingModeTo(false);
00463   }
00464 
00465   radio->cleanAnalogueModelUntil(earliestInfoPoint);
00466 }
00467 
00468 void BasePhyLayer::handleUpperMessage(cMessage* msg){
00469 
00470   // check if Radio is in TX state
00471   if (radio->getCurrentState() != Radio::TX)
00472   {
00473         delete msg;
00474         msg = 0;
00475     opp_error("Error: message for sending received, but radio not in state TX");
00476   }
00477 
00478   // check if not already sending
00479   if(txOverTimer->isScheduled())
00480   {
00481         delete msg;
00482         msg = 0;
00483     opp_error("Error: message for sending received, but radio already sending");
00484   }
00485 
00486   // build the AirFrame to send
00487   assert(dynamic_cast<cPacket*>(msg) != 0);
00488 
00489   AirFrame* frame = encapsMsg(static_cast<cPacket*>(msg));
00490 
00491   // make sure there is no self message of kind TX_OVER scheduled
00492   // and schedule the actual one
00493   assert (!txOverTimer->isScheduled());
00494   sendSelfMessage(txOverTimer, simTime() + frame->getDuration());
00495 
00496   sendMessageDown(frame);
00497 }
00498 
00499 AirFrame *BasePhyLayer::encapsMsg(cPacket *macPkt)
00500 {
00501   // the cMessage passed must be a MacPacket... but no cast needed here
00502   // MacPkt* pkt = static_cast<MacPkt*>(msg);
00503 
00504   // ...and must always have a ControlInfo attached (contains Signal)
00505   cObject* ctrlInfo = macPkt->removeControlInfo();
00506   assert(ctrlInfo);
00507 
00508   // create the new AirFrame
00509   AirFrame* frame = new AirFrame(macPkt->getName(), AIR_FRAME);
00510 
00511   MacToPhyControlInfo* macToPhyCI = static_cast<MacToPhyControlInfo*>(ctrlInfo);
00512 
00513 
00514 
00515   // Retrieve the pointer to the Signal-instance from the ControlInfo-instance.
00516   // We are now the new owner of this instance.
00517   Signal* s = macToPhyCI->retrieveSignal();
00518   // make sure we really obtained a pointer to an instance
00519   assert(s);
00520 
00521   // put host move pattern to Signal
00522   s->setMove(move);
00523 
00524   // set the members
00525   assert(s->getSignalLength() > 0);
00526   frame->setDuration(s->getSignalLength());
00527   // copy the signal into the AirFrame
00528   frame->setSignal(*s);
00529   //set priority of AirFrames above the normal priority to ensure
00530   //channel consistency (before any thing else happens at a time
00531   //point t make sure that the channel has removed every AirFrame
00532   //ended at t and added every AirFrame started at t)
00533   frame->setSchedulingPriority(airFramePriority);
00534   frame->setProtocolId(myProtocolId());
00535   frame->setBitLength(headerLength);
00536   frame->setId(world->getUniqueAirFrameId());
00537   frame->setChannel(radio->getCurrentChannel());
00538 
00539 
00540   // pointer and Signal not needed anymore
00541   delete s;
00542   s = 0;
00543 
00544 
00545 
00546   // delete the Control info
00547   delete macToPhyCI;
00548   macToPhyCI = 0;
00549   ctrlInfo = 0;
00550 
00551 
00552 
00553 
00554 
00555   frame->encapsulate(macPkt);
00556 
00557   // --- from here on, the AirFrame is the owner of the MacPacket ---
00558   macPkt = 0;
00559   coreEV <<"AirFrame encapsulated, length: " << frame->getBitLength() << "\n";
00560 
00561   return frame;
00562 }
00563 
00564 void BasePhyLayer::handleChannelSenseRequest(cMessage* msg) {
00565   ChannelSenseRequest* senseReq = static_cast<ChannelSenseRequest*>(msg);
00566 
00567   simtime_t nextHandleTime = decider->handleChannelSenseRequest(senseReq);
00568 
00569   if(nextHandleTime >= simTime()) { //schedule request for next handling
00570     sendSelfMessage(msg, nextHandleTime);
00571 
00572     //don't throw away any AirFrames while ChannelSenseRequest is active
00573     if(!channelInfo.isRecording()) {
00574       channelInfo.startRecording(simTime());
00575     }
00576   } else if(nextHandleTime >= 0.0){
00577     opp_error("Next handle time of ChannelSenseRequest returned by the Decider is smaller then current simulation time: %.2f",
00578         SIMTIME_DBL(nextHandleTime));
00579   }
00580 
00581   // else, i.e. nextHandleTime < 0.0, the Decider doesn't want to handle
00582   // the request again
00583 }
00584 
00585 void BasePhyLayer::handleUpperControlMessage(cMessage* msg){
00586 
00587   switch(msg->getKind()) {
00588   case CHANNEL_SENSE_REQUEST:
00589     handleChannelSenseRequest(msg);
00590     break;
00591   default:
00592     ev << "Received unknown control message from upper layer!" << endl;
00593     break;
00594   }
00595 }
00596 
00597 void BasePhyLayer::handleSelfMessage(cMessage* msg) {
00598 
00599   switch(msg->getKind()) {
00600   //transmission over
00601   case TX_OVER:
00602     assert(msg == txOverTimer);
00603     sendControlMsg(new cMessage("Transmission over", TX_OVER));
00604     break;
00605 
00606   //radio switch over
00607   case RADIO_SWITCHING_OVER:
00608     assert(msg == radioSwitchingOverTimer);
00609     finishRadioSwitching();
00610     break;
00611 
00612   //AirFrame
00613   case AIR_FRAME:
00614     handleAirFrame(msg);
00615     break;
00616 
00617   //ChannelSenseRequest
00618   case CHANNEL_SENSE_REQUEST:
00619     handleChannelSenseRequest(msg);
00620     break;
00621 
00622   default:
00623     break;
00624   }
00625 }
00626 
00627 //--Send messages------------------------------
00628 
00629 void BasePhyLayer::sendControlMessageUp(cMessage* msg) {
00630   send(msg, upperControlOut);
00631 }
00632 
00633 void BasePhyLayer::sendMacPktUp(cMessage* pkt) {
00634   send(pkt, upperGateOut);
00635 }
00636 
00637 void BasePhyLayer::sendMessageDown(AirFrame* msg) {
00638 
00639   sendToChannel(msg);
00640 }
00641 
00642 void BasePhyLayer::sendSelfMessage(cMessage* msg, simtime_t time) {
00643   //TODO: maybe delete this method because it doesn't makes much sense,
00644   //    or change it to "scheduleIn(msg, timeDelta)" which schedules
00645   //    a message to +timeDelta from current time
00646   scheduleAt(time, msg);
00647 }
00648 
00649 
00650 void BasePhyLayer::filterSignal(Signal& s) {
00651   for(AnalogueModelList::const_iterator it = analogueModels.begin();
00652     it != analogueModels.end(); it++) {
00653 
00654     AnalogueModel* tmp = *it;
00655     tmp->filterSignal(s);
00656   }
00657 }
00658 
00659 //--Destruction--------------------------------
00660 
00661 BasePhyLayer::~BasePhyLayer() {
00662   //get AirFrames from ChannelInfo and delete
00663   //(although ChannelInfo normally owns the AirFrames it
00664   //is not able to cancel and delete them itself
00665   AirFrameVector channel;
00666   channelInfo.getAirFrames(0, simTime(), channel);
00667 
00668   for(AirFrameVector::iterator it = channel.begin();
00669     it != channel.end(); ++it)
00670   {
00671     cancelAndDelete(*it);
00672   }
00673 
00674   //free timer messages
00675   if(txOverTimer) {
00676     cancelAndDelete(txOverTimer);
00677   }
00678   if(radioSwitchingOverTimer) {
00679         cancelAndDelete(radioSwitchingOverTimer);
00680   }
00681 
00682   //free thermal noise mapping
00683   if(thermalNoise) {
00684     delete thermalNoise;
00685   }
00686 
00687   //free Decider
00688   if(decider != 0) {
00689     delete decider;
00690   }
00691 
00692   /*
00693    * get a pointer to the radios RSAM again to avoid deleting it,
00694    * it is not created by calling new (BasePhyLayer is not the owner)!
00695    */
00696   AnalogueModel* rsamPointer = radio->getAnalogueModel();
00697 
00698   //free AnalogueModels
00699   for(AnalogueModelList::iterator it = analogueModels.begin();
00700     it != analogueModels.end(); it++) {
00701 
00702     AnalogueModel* tmp = *it;
00703 
00704     // do not delete the RSAM, it's not allocated by new!
00705     if (tmp == rsamPointer)
00706     {
00707       rsamPointer = 0;
00708       continue;
00709     }
00710 
00711     if(tmp != 0) {
00712       delete tmp;
00713     }
00714   }
00715 
00716 
00717   // free radio
00718   if(radio != 0)
00719   {
00720     delete radio;
00721   }
00722 }
00723 
00724 //--MacToPhyInterface implementation-----------------------
00725 
00726 int BasePhyLayer::getRadioState() {
00727   Enter_Method_Silent();
00728   assert(radio);
00729   return radio->getCurrentState();
00730 }
00731 
00732 void BasePhyLayer::finishRadioSwitching()
00733 {
00734   radio->endSwitch(simTime());
00735   sendControlMsg(new cMessage("Radio switching over", RADIO_SWITCHING_OVER));
00736 }
00737 
00738 simtime_t BasePhyLayer::setRadioState(int rs) {
00739   Enter_Method_Silent();
00740   assert(radio);
00741 
00742   if(txOverTimer && txOverTimer->isScheduled()) {
00743     opp_warning("Switched radio while sending an AirFrame. The effects this would have on the transmission are not simulated by the BasePhyLayer!");
00744   }
00745 
00746   simtime_t switchTime = radio->switchTo(rs, simTime());
00747 
00748   //invalid switch time, we are probably already switching
00749   if(switchTime < 0)
00750     return switchTime;
00751 
00752   // if switching is done in exactly zero-time no extra self-message is scheduled
00753   if (switchTime == 0.0)
00754   {
00755     // TODO: in case of zero-time-switch, send no control-message to mac!
00756     // maybe call a method finishRadioSwitchingSilent()
00757     finishRadioSwitching();
00758   } else
00759   {
00760     sendSelfMessage(radioSwitchingOverTimer, simTime() + switchTime);
00761   }
00762 
00763   return switchTime;
00764 }
00765 
00766 ChannelState BasePhyLayer::getChannelState() {
00767   Enter_Method_Silent();
00768   assert(decider);
00769   return decider->getChannelState();
00770 }
00771 
00772 int BasePhyLayer::getPhyHeaderLength() {
00773   Enter_Method_Silent();
00774   return par("headerLength").longValue();
00775 }
00776 
00777 void BasePhyLayer::setCurrentRadioChannel(int newRadioChannel) {
00778   if(txOverTimer && txOverTimer->isScheduled()) {
00779     opp_warning("Switched channel while sending an AirFrame. The effects this would have on the transmission are not simulated by the BasePhyLayer!");
00780   }
00781 
00782   radio->setCurrentChannel(newRadioChannel);
00783   decider->channelChanged(newRadioChannel);
00784   coreEV << "Switched radio to channel " << newRadioChannel << endl;
00785 }
00786 
00787 int BasePhyLayer::getCurrentRadioChannel() {
00788   return radio->getCurrentChannel();
00789 }
00790 
00791 int BasePhyLayer::getNbRadioChannels() {
00792   return par("nbRadioChannels");
00793 }
00794 
00795 //--DeciderToPhyInterface implementation------------
00796 
00797 void BasePhyLayer::getChannelInfo(simtime_t from, simtime_t to, AirFrameVector& out) {
00798   channelInfo.getAirFrames(from, to, out);
00799 }
00800 
00801 ConstMapping* BasePhyLayer::getThermalNoise(simtime_t from, simtime_t to) {
00802   if(thermalNoise)
00803     thermalNoise->initializeArguments(Argument(from));
00804 
00805   return thermalNoise;
00806 }
00807 
00808 void BasePhyLayer::sendControlMsg(cMessage* msg) {
00809   if(msg->getKind() == CHANNEL_SENSE_REQUEST) {
00810     if(channelInfo.isRecording()) {
00811       channelInfo.stopRecording();
00812     }
00813   }
00814   sendControlMessageUp(msg);
00815 }
00816 
00817 void BasePhyLayer::sendUp(AirFrame* frame, DeciderResult* result) {
00818 
00819   coreEV << "Decapsulating MacPacket from Airframe with ID " << frame->getId() << " and sending it up to MAC." << endl;
00820 
00821   cMessage* packet = frame->decapsulate();
00822 
00823   assert(packet);
00824 
00825   PhyToMacControlInfo* ctrlInfo = new PhyToMacControlInfo(result);
00826 
00827   packet->setControlInfo(ctrlInfo);
00828 
00829   sendMacPktUp(packet);
00830 }
00831 
00832 simtime_t BasePhyLayer::getSimTime() {
00833 
00834   return simTime();
00835 }
00836 
00837 void BasePhyLayer::cancelScheduledMessage(cMessage* msg) {
00838   if(msg->isScheduled()){
00839     cancelEvent(msg);
00840   } else {
00841     EV << "Warning: Decider wanted to cancel a scheduled message but message"
00842        << " wasn't actually scheduled. Message is: " << msg << endl;
00843   }
00844 }
00845 
00846 void BasePhyLayer::rescheduleMessage(cMessage* msg, simtime_t t) {
00847   cancelScheduledMessage(msg);
00848   scheduleAt(t, msg);
00849 }
00850 
00851 void BasePhyLayer::drawCurrent(double amount, int activity) {
00852   BatteryAccess::drawCurrent(amount, activity);
00853 }
00854 
00855 BaseUtility* BasePhyLayer::getUtility() {
00856   return utility;
00857 }
00858 
00859 BaseWorldUtility* BasePhyLayer::getWorldUtility() {
00860   return world;
00861 }
00862 
00863 void BasePhyLayer::recordScalar(const char *name, double value, const char *unit) {
00864   ChannelAccess::recordScalar(name, value, unit);
00865 }