![]() |
User Manual, Developers Guide and API Documentation |
![]() |
00001 /******************************************************************************* 00002 * This file is part of openWNS (open Wireless Network Simulator) 00003 * _____________________________________________________________________________ 00004 * 00005 * Copyright (C) 2004-2009 00006 * Chair of Communication Networks (ComNets) 00007 * Kopernikusstr. 5, D-52074 Aachen, Germany 00008 * email: info@openwns.org 00009 * www: http://www.openwns.org 00010 * _____________________________________________________________________________ 00011 * 00012 * openWNS is free software; you can redistribute it and/or modify it under the 00013 * terms of the GNU Lesser General Public License version 2 as published by the 00014 * Free Software Foundation; 00015 * 00016 * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY 00017 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00018 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00019 * details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public License 00022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 * 00024 ******************************************************************************/ 00025 00026 00027 #include <WIMAC/frame/TimingControl.hpp> 00028 00029 #include <utility> 00030 00031 #include <WNS/pyconfig/View.hpp> 00032 #include <WNS/ldk/Layer.hpp> 00033 #include <WNS/ldk/fcf/FrameBuilder.hpp> 00034 #include <WNS/ldk/fcf/CompoundCollector.hpp> 00035 #include <WNS/probe/bus/ContextProviderCollection.hpp> 00036 #include <WNS/probe/bus/ContextCollector.hpp> 00037 #include <boost/bind.hpp> 00038 00039 #include <WIMAC/Logger.hpp> 00040 #include <WIMAC/parameter/PHY.hpp> 00041 00042 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00043 wimac::frame::TimingControl, 00044 wns::ldk::fcf::TimingControlInterface, 00045 "wimac.frame.TimingControl", 00046 wns::ldk::fcf::FrameBuilderConfigCreator ); 00047 00048 using namespace wimac::frame; 00049 00050 namespace wimac { namespace frame { 00051 00052 00053 class TriggerActivationStart 00054 { 00055 public: 00056 TriggerActivationStart(TimingControl* timingControl) : 00057 timingControl_(timingControl) {} 00058 00059 void operator()() 00060 { 00061 timingControl_->startProcessingActivations(); 00062 } 00063 00064 private: 00065 TimingControl* timingControl_; 00066 }; 00067 } 00068 } 00069 00070 TimingControl::TimingControl( wns::ldk::fcf::FrameBuilder* fb, const wns::pyconfig::View& config) : 00071 wns::ldk::fcf::TimingControlInterface(), 00072 frameBuilder_(fb), 00073 running_(false), 00074 config_(config), 00075 frameStartupDelay_(config.get<wns::simulator::Time>("frameStartupDelay")) 00076 { 00077 assure( config.knows("activations"), 00078 "Activations are not specified in TimingControl" ); 00079 00080 wns::probe::bus::ContextProviderCollection& cpc = 00081 getFrameBuilder()->getFUN()->getLayer()->getContextProviderCollection(); 00082 00083 cpc.addProvider(wns::probe::bus::contextprovider::Callback( 00084 "OffsetFromFrameStart", 00085 boost::bind(&TimingControl::getOffset, this))); 00086 00087 } 00088 00089 void TimingControl::start() 00090 { 00091 activeCC_ = activations_.end(); 00092 running_ = true; 00093 00094 if ( !this->hasPeriodicTimeoutSet() ) 00095 this->startPeriodicTimeout(parameter::ThePHY::getInstance()->getFrameDuration()); 00096 00097 // to allow first frame to begin immediately do: 00098 // this->periodically(); 00099 } 00100 00101 void TimingControl::pause() 00102 { 00103 running_ = false; 00104 activeCC_ = activations_.end(); 00105 } 00106 00107 void TimingControl::stop() 00108 { 00109 this->cancelPeriodicTimeout(); 00110 this->cancelTimeout(); 00111 activeCC_ = activations_.end(); 00112 running_ = false; 00113 } 00114 00115 00116 void TimingControl::configure() 00117 { 00118 onFUNCreated(); 00119 } 00120 00121 void TimingControl::onFUNCreated() 00122 { 00123 double sumDuration = 0.0; 00124 00125 for ( int i = 0; i < config_.len("activations"); ++i ) { 00126 wns::pyconfig::View activationConfig( config_, "activations", i ); 00127 00128 int mode = activationConfig.get<int>("mode.mode"); 00129 double duration = activationConfig.get<double>("duration"); 00130 int action = activationConfig.get<int>("action.action"); 00131 00132 wns::ldk::fcf::CompoundCollector* compoundCollector; 00133 00134 if(action != TimingControl::Pause){ 00135 00136 std::string ccName = activationConfig.get<std::string>("compoundCollector"); 00137 00138 compoundCollector = ( getFrameBuilder()->getFUN()-> 00139 findFriend<wns::ldk::fcf::CompoundCollector*>(ccName)); 00140 00141 if (!compoundCollector) { 00142 std::stringstream ss; 00143 ss << "FU " << ccName << " is not a compound collector, " 00144 << "unable to register action for " << ccName; 00145 throw wns::Exception(ss.str()); 00146 } 00147 00148 compoundCollector->setFrameBuilder( getFrameBuilder() ); 00149 00150 LOG_INFO( getFrameBuilder()->getFUN()->getName(), 00151 ": new activation entry for CC: ", 00152 compoundCollector->getName(), ", with mode: ", 00153 wns::ldk::fcf::CompoundCollector::mode2String(mode), 00154 ", action: ", action, ", and duration: ", duration); 00155 } 00156 else if(action == TimingControl::Pause){ 00157 // there is no compound collector needed for Pause Activations 00158 compoundCollector = NULL; 00159 00160 LOG_INFO( getFrameBuilder()->getFUN()->getName(), 00161 ": new Pause activation entry with mode: ", 00162 wns::ldk::fcf::CompoundCollector::mode2String(mode), 00163 ", action: ", action, ", and duration: ", duration); 00164 } 00165 00166 ActivationEntry entry; 00167 entry.mode = mode; 00168 entry.action = action; 00169 entry.compoundCollector = compoundCollector; 00170 entry.duration = duration; 00171 00172 if(action == TimingControl::Start && action || action == TimingControl::Pause){ 00173 // only these actions are really time consuming 00174 sumDuration += duration; 00175 } 00176 00177 activations_.push_back( entry ); 00178 00179 } 00180 LOG_INFO( getFrameBuilder()->getFUN()->getName(), " ", activations_.size(), 00181 " activations registered at timing control, sum duration: ", 00182 sumDuration, ", frame duration is: ", 00183 parameter::ThePHY::getInstance()->getFrameDuration()); 00184 00185 LOG_INFO( "difference is ", 00186 parameter::ThePHY::getInstance()->getFrameDuration() - sumDuration ); 00187 00188 assure(sumDuration <= parameter::ThePHY::getInstance()->getFrameDuration(), 00189 "the sum of all phases does not fit into the frame duration"); 00190 00191 activeCC_ = activations_.end(); 00192 //timeoutIsForMe = activations_.end(); 00193 } 00194 00195 00196 #ifndef WNS_NDEBUG 00197 void TimingControl::finishedPhase(wns::ldk::fcf::CompoundCollectorInterface* collector) 00198 #else 00199 void TimingControl::finishedPhase(wns::ldk::fcf::CompoundCollectorInterface*) 00200 #endif 00201 { 00202 assure(activeCC_->compoundCollector == collector, 00203 "An inactive compound collector has reported to have finished."); 00204 00205 //assure(timeoutIsForMe == activeCC_, "current timeout is not right"); 00206 00207 assure(this->hasTimeoutSet(), 00208 "the current phase (the last one?) finished after the final phase!?"); 00209 00210 if ( activeCC_ == activations_.end() ) 00211 { 00212 std::stringstream ss; 00213 ss << "timing inconsistency" << std::endl; 00214 ss << "nextPhase() called, but no active compound collector in "; 00215 ss << getFrameBuilder()->getFUN()->getLayer()->getName() << std::endl; 00216 throw wns::Exception( ss.str() ); 00217 } 00218 00219 LOG_INFO( getFrameBuilder()->getFUN()->getLayer()->getName(), " current phase has finished"); 00220 00221 //if you want that the phases start subsequently do: 00222 // this->cancelTimeout(); 00223 // this->onTimeout(); 00224 } 00225 00226 void 00227 TimingControl::periodically() 00228 { 00229 //Notify NewFrame-Observers about newFrame 00230 frameBuilder_->notifyNewFrameObservers(); 00231 00232 frameStartTime_ = wns::simulator::getEventScheduler()->getTime(); 00233 00234 // Only continue if running == true 00235 if ( !running_ ) 00236 return; 00237 00238 TriggerActivationStart event (this); 00239 00240 wns::simulator::getEventScheduler() 00241 ->schedule(event, frameStartTime_ + frameStartupDelay_ ); 00242 } 00243 00244 void 00245 TimingControl::startProcessingActivations() 00246 { 00247 // Frame duration ends before last timing node is called 00248 if ( activeCC_ != activations_.end()) 00249 { 00250 LOG_WARN( getFrameBuilder()->getFUN()->getLayer()->getName(), 00251 ": FrameBuilder has not yet finished current frame"); 00252 } 00253 00254 LOG_INFO( getFrameBuilder()->getFUN()->getName(), ": Starting Frame"); 00255 00256 activeCC_ = activations_.begin(); 00257 processOneActivation(); 00258 } 00259 00260 void 00261 TimingControl::onTimeout() 00262 { 00263 LOG_INFO(getFrameBuilder()->getFUN()->getName()," TimingControl received timeout"); 00264 00265 if (activeCC_->compoundCollector){ 00266 // pause activations do not have a compound collector 00267 activeCC_->compoundCollector->stop(); 00268 } 00269 00270 ++activeCC_; 00271 00272 if ( activeCC_ != activations_.end() ){ 00273 LOG_TRACE( getFrameBuilder()->getFUN()->getName(), ": Next Activation" ); 00274 processOneActivation(); 00275 00276 } else { 00277 LOG_INFO( getFrameBuilder()->getFUN()->getName(), 00278 ": Last compound collector finished"); 00279 } 00280 } 00281 00282 void 00283 TimingControl::processOneActivation() 00284 { 00285 assure( activeCC_ != activations_.end(), "cannot process empty activation" ); 00286 00287 while ( activeCC_->action == TimingControl::StartCollection || 00288 activeCC_->action == TimingControl::FinishCollection ) { 00289 00290 switch ( activeCC_->action ) { 00291 case TimingControl::StartCollection: 00292 activeCC_->compoundCollector->setMaximumDuration( activeCC_->duration ); 00293 activeCC_->compoundCollector->startCollection( activeCC_->mode ); 00294 break; 00295 case TimingControl::FinishCollection: 00296 activeCC_->compoundCollector->finishCollection(); 00297 break; 00298 default: 00299 throw wns::Exception("Unknown activation in Timing Control"); 00300 } 00301 ++activeCC_; 00302 } 00303 00304 if ( activeCC_ == activations_.end() ) 00305 return; 00306 00307 switch ( activeCC_->action ) { 00308 00309 case TimingControl::Start: 00310 activeCC_->compoundCollector->setMaximumDuration( activeCC_->duration ); 00311 activeCC_->compoundCollector->start( activeCC_->mode ); 00312 00313 //set timeout to end of this phase 00314 this->setTimeout( (*activeCC_).duration ); 00315 00316 LOG_INFO( getFrameBuilder()->getFUN()->getName(), ": next phase activated with a duration of ", 00317 (*activeCC_).duration ); 00318 break; 00319 00320 case TimingControl::Pause: 00321 //set timeout to end of this phase 00322 this->setTimeout( (*activeCC_).duration ); 00323 00324 LOG_INFO( getFrameBuilder()->getFUN()->getName(), ": pause for a duration of ", 00325 (*activeCC_).duration ); 00326 break; 00327 default: 00328 throw wns::Exception("Illegal activation entry in " + 00329 getFrameBuilder()->getFUN()->getName()); 00330 } 00331 } 00332 00333 int 00334 TimingControl::getOffset() 00335 { 00336 simTimeType now = wns::simulator::getEventScheduler()->getTime(); 00337 double offset = now - frameStartTime_; 00338 int symOffset = int(offset / parameter::ThePHY::getInstance()->getSymbolDuration()); 00339 return symOffset; 00340 }
1.5.5