![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /****************************************************************************** 00002 * WiMeMac * 00003 * This file is part of openWNS (open Wireless Network Simulator) 00004 * _____________________________________________________________________________ 00005 * 00006 * Copyright (C) 2004-2011 00007 * Chair of Communication Networks (ComNets) 00008 * Kopernikusstr. 5, D-52074 Aachen, Germany 00009 * phone: ++49-241-80-27910, 00010 * fax: ++49-241-80-22242 00011 * email: info@openwns.org 00012 * www: http://www.openwns.org 00013 * _____________________________________________________________________________ 00014 * 00015 * openWNS is free software; you can redistribute it and/or modify it under the 00016 * terms of the GNU Lesser General Public License version 2 as published by the 00017 * Free Software Foundation; 00018 * 00019 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00020 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00021 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00022 * details. 00023 * 00024 * You should have received a copy of the GNU Lesser General Public License 00025 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00026 * 00027 ******************************************************************************/ 00028 00029 #include <WIMEMAC/convergence/PhyUser.hpp> 00030 #include <WNS/ldk/fun/FUN.hpp> 00031 #include <WNS/pyconfig/View.hpp> 00032 #include <WNS/logger/Logger.hpp> 00033 #include <WNS/module/Base.hpp> 00034 #include <WNS/ldk/concatenation/Concatenation.hpp> 00035 00036 using namespace wimemac::convergence; 00037 00038 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00039 wimemac::convergence::PhyUser, 00040 wns::ldk::FunctionalUnit, 00041 "wimemac.convergence.PhyUser", 00042 wns::ldk::FUNConfigCreator); 00043 00044 PhyUser::PhyUser(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& _config) : 00045 wns::ldk::fu::Plain<PhyUser, PhyUserCommand>(fun), 00046 config(_config), 00047 logger(config.get<wns::pyconfig::View>("logger")), 00048 tune(), 00049 dataTransmission(NULL), 00050 notificationService(NULL), 00051 phyModes(config.getView("phyModesDeliverer")), 00052 managerName(config.get<std::string>("managerName")), 00053 txDurationCommandName(config.get<std::string>("txDurationCommandName")), 00054 txrxTurnaroundDelay(config.get<wns::simulator::Time>("txrxTurnaroundDelay")), 00055 phyUserStatus(receiving), 00056 currentTxCompound(), 00057 rxProbe_(new wns::probe::bus::ContextCollector(wns::probe::bus::ContextProviderCollection(&fun->getLayer()->getContextProviderCollection()), 00058 "wimemac.phyuser.rxPower")), 00059 interferenceProbe_(new wns::probe::bus::ContextCollector(wns::probe::bus::ContextProviderCollection(&fun->getLayer()->getContextProviderCollection()), 00060 "wimemac.phyuser.interferencePower")), 00061 SINRProbe_(new wns::probe::bus::ContextCollector(wns::probe::bus::ContextProviderCollection(&fun->getLayer()->getContextProviderCollection()), 00062 "wimemac.phyuser.SINR")), 00063 SINRweightedProbe_(new wns::probe::bus::ContextCollector(wns::probe::bus::ContextProviderCollection(&fun->getLayer()->getContextProviderCollection()), 00064 "wimemac.phyuser.SINRweighted")) 00065 { 00066 tune.frequency = config.get<double>("initFrequency"); 00067 tune.bandwidth = config.get<double>("initBandwidthMHz"); 00068 tune.numberOfSubCarrier = 1; 00069 00070 MESSAGE_SINGLE(NORMAL, logger, "Signal frequency is set to " << tune.frequency); 00071 } 00072 // PhyUser 00073 00074 00075 PhyUser::~PhyUser() 00076 { 00077 00078 } 00079 00080 void PhyUser::onFUNCreated() 00081 { 00082 friends.manager = getFUN()->findFriend<wimemac::lowerMAC::Manager*>(managerName); 00083 } // onFUNCreated 00084 00085 bool PhyUser::doIsAccepting(const wns::ldk::CompoundPtr& /* compound */) const 00086 { 00087 // we only accept if we are not currently transmitting 00088 return (phyUserStatus != transmitting); 00089 } // isAccepting 00090 00091 00092 00093 void PhyUser::doSendData(const wns::ldk::CompoundPtr& compound) 00094 { 00095 assure(compound, "sendData called with an invalid compound."); 00096 assure(phyUserStatus != transmitting, "Cannot send data during transmission"); 00097 00098 MESSAGE_SINGLE(NORMAL, logger, "Rx Frequency is set to: " << (dataTransmission->getRxTune()).frequency); 00099 MESSAGE_SINGLE(NORMAL, logger, "Tx Frequency is set to: " << (dataTransmission->getTxTune()).frequency); 00100 00101 if(!friends.manager->isPreamble(compound->getCommandPool())) 00102 { 00103 // signal tx start to the MAC 00104 this->wns::Subject<ITxStartEnd>::forEachObserver(OnTxStartEnd(compound, start)); 00105 } 00106 00107 wns::simulator::Time frameTxDuration = getFUN()->getCommandReader(txDurationCommandName)-> 00108 readCommand<wimemac::convergence::TxDurationSetterCommand>(compound->getCommandPool())->getDuration(); 00109 00110 PhyUserCommand* command = activateCommand(compound->getCommandPool()); 00111 00112 // generate functor 00113 wimemac::convergence::BroadcastOFDMAAccessFunc* func = new wimemac::convergence::BroadcastOFDMAAccessFunc; 00114 00115 // transmit now 00116 func->transmissionStart = wns::simulator::getEventScheduler()->getTime(); 00117 func->transmissionStop = wns::simulator::getEventScheduler()->getTime() + frameTxDuration; 00118 func->subBand = 1; 00119 00120 command->local.pAFunc.reset(func); 00121 (*command->local.pAFunc.get())(this, compound); 00122 00123 MESSAGE_SINGLE(NORMAL, logger, "Transmission, rx disabled for " << frameTxDuration); 00124 if(phyUserStatus == txrxTurnaround) 00125 { 00126 setNewTimeout(frameTxDuration); 00127 } 00128 else 00129 { 00130 setTimeout(frameTxDuration); 00131 } 00132 // we are transmitting! 00133 phyUserStatus = transmitting; 00134 00135 this->currentTxCompound = compound; 00136 00137 MESSAGE_SINGLE(NORMAL, logger, "onSendData: Compound " << *(compound)); 00138 00139 } // doSendData 00140 00141 void PhyUser::doOnData(const wns::ldk::CompoundPtr& compound) 00142 { 00143 assure(compound, "onData called with an invalid compound."); 00144 00145 getDeliverer()->getAcceptor(compound)->onData(compound); 00146 } // doOnData 00147 00148 void PhyUser::onData(wns::osi::PDUPtr pdu, wns::service::phy::power::PowerMeasurementPtr rxPowerMeasurement) 00149 { 00150 assure(wns::dynamicCast<wns::ldk::Compound>(pdu), "not a CompoundPtr"); 00151 00152 if(phyUserStatus != receiving) 00153 { 00154 // During transmission, the receiver is off 00155 return; 00156 } 00157 00158 // FIRST: create a copy instead of working on the real compound 00159 wns::ldk::CompoundPtr compound = wns::staticCast<wns::ldk::Compound>(pdu)->copy(); 00160 00161 PhyUserCommand* phyCommand = getCommand(compound->getCommandPool()); 00162 00163 // store measured signal into Command 00164 phyCommand->local.rxPower = rxPowerMeasurement->getRxPower(); 00165 phyCommand->local.interference = rxPowerMeasurement->getInterferencePower(); 00166 00167 00168 // MESSAGE_SINGLE(NORMAL, logger, "onData: rxPower " << phyCommand->local.rxPower); 00169 // MESSAGE_SINGLE(NORMAL, logger, "onData: interference " << phyCommand->local.interference); 00170 // MESSAGE_SINGLE(NORMAL, logger, "onData: Compound " << *(compound)); 00171 00172 // set probe values 00173 if(friends.manager->isForMe(compound->getCommandPool() ) && !friends.manager->isBeacon(compound->getCommandPool() )) 00174 { 00175 wns::Ratio sinr_ = wns::Ratio::from_dB(phyCommand->local.rxPower.get_dBm() - phyCommand->local.interference.get_dBm()); 00176 00177 rxProbe_->put(phyCommand->local.rxPower.get_dBm()); 00178 interferenceProbe_->put(phyCommand->local.interference.get_dBm()); 00179 SINRProbe_->put(sinr_.get_dB() ); 00180 00181 // Write weighted SINR probe; probe is weighted according to the tx duration in µs 00182 wns::simulator::Time txDuration_ = getFUN()->getCommandReader(txDurationCommandName)-> 00183 readCommand<wimemac::convergence::TxDurationSetterCommand>(compound->getCommandPool())->getDuration(); 00184 00185 int weightingFactor_ = ceil(txDuration_*1E6); // weightingFactor = number of µs of tx duration 00186 for (int i = 0; i < weightingFactor_; i++) 00187 { 00188 SINRweightedProbe_->put(sinr_.get_dB() ); 00189 } 00190 } 00191 00192 this->wns::ldk::FunctionalUnit::onData(compound); 00193 } // onData 00194 00195 void PhyUser::setDataTransmissionService(wns::service::Service* phy) 00196 { 00197 assure(phy, "must be non-NULL"); 00198 assureType(phy, wns::service::phy::ofdma::DataTransmission*); 00199 dataTransmission = dynamic_cast<wns::service::phy::ofdma::DataTransmission*>(phy); 00200 dataTransmission->setRxTune(tune); 00201 dataTransmission->setTxTune(tune); 00202 } // setDataTransmissionService 00203 00204 wns::service::phy::ofdma::DataTransmission* PhyUser::getDataTransmissionService() const 00205 { 00206 assure(dataTransmission, "no ofdma::DataTransmission set. Did you call setDataTransmission()?"); 00207 return dataTransmission; 00208 } // getDataTransmissionService 00209 00210 void PhyUser::setNotificationService(wns::service::Service* phy) 00211 { 00212 assure(phy, "must be non-NULL"); 00213 assureType(phy, wns::service::phy::ofdma::Notification*); 00214 notificationService = dynamic_cast<wns::service::phy::ofdma::Notification*>(phy); 00215 00216 // attach handler (there can be only one) 00217 notificationService->registerHandler(this); 00218 00219 } // setNotificationService 00220 00221 wns::service::phy::ofdma::Notification* PhyUser::getNotificationService() const 00222 { 00223 assure(notificationService, "no ofdma::Notification set. Did you call setNotificationService()?"); 00224 return notificationService; 00225 } // getNotificationService 00226 00227 void PhyUser::doWakeup() 00228 { 00229 assure(false, "PhyUser doWakeup will never be called -- nobody is below"); 00230 } // doWakeup 00231 00232 void PhyUser::onTimeout() 00233 { 00234 assure(phyUserStatus != receiving, "Timeout although not transmitting"); 00235 if(phyUserStatus == transmitting) 00236 { 00237 // finished transmission, start turnaround 00238 MESSAGE_SINGLE(NORMAL, logger, "Timeout, finished transmission"); 00239 phyUserStatus = txrxTurnaround; 00240 setTimeout(txrxTurnaroundDelay); 00241 00242 assure(this->currentTxCompound, "currentTxCompound is NULL"); 00243 if(!friends.manager->isPreamble(this->currentTxCompound->getCommandPool())) 00244 { 00245 // signal tx end to MAC 00246 MESSAGE_SINGLE(NORMAL, logger, "No preamble -> signal tx end"); 00247 this->wns::Subject<ITxStartEnd>::forEachObserver(OnTxStartEnd(this->currentTxCompound, end)); 00248 } 00249 this->currentTxCompound = wns::ldk::CompoundPtr(); 00250 00251 // wakeup: we are ready to transmit another compound 00252 this->getReceptor()->wakeup(); 00253 return; 00254 } 00255 00256 if(phyUserStatus == txrxTurnaround) 00257 { 00258 // finished turnaround, ready to receive 00259 phyUserStatus = receiving; 00260 return; 00261 } 00262 00263 assure(false, "Unknown phyUserStatus"); 00264 } 00265 00266 void PhyUser::setFrequency(double frequency) 00267 { 00268 if(dataTransmission == NULL) 00269 { 00270 MESSAGE_SINGLE(NORMAL, logger, "cannot yet set RxFrequency, save for after initialisation"); 00271 tune.frequency = frequency; 00272 } 00273 else 00274 { 00275 MESSAGE_SINGLE(NORMAL, logger, "setRxFrequency to f: " << frequency << " MHz"); 00276 tune.frequency = frequency; 00277 dataTransmission->setRxTune(tune); 00278 dataTransmission->setTxTune(tune); 00279 } 00280 } 00281 00282 PhyModeProvider* PhyUser::getPhyModeProvider() 00283 { 00284 return &phyModes; 00285 } 00286 00287 wns::Power 00288 PhyUser::getRxPower(const wns::ldk::CommandPool* commandPool) 00289 { 00290 PhyUserCommand* phyCommand = getCommand(commandPool); 00291 return phyCommand->local.rxPower; 00292 } 00293 00294 wns::Power 00295 PhyUser::getInterference(const wns::ldk::CommandPool* commandPool) 00296 { 00297 PhyUserCommand* phyCommand = getCommand(commandPool); 00298 return phyCommand->local.interference; 00299 } 00300
1.5.5