User Manual, Developers Guide and API Documentation

TimingControl.cpp

Go to the documentation of this file.
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 }

Generated on Sun May 27 03:31:43 2012 for openWNS by  doxygen 1.5.5