![]() |
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/FrameSynchronization.hpp> 00030 #include <WIMEMAC/convergence/PhyUser.hpp> 00031 #include <WIMEMAC/convergence/PreambleGenerator.hpp> 00032 00033 #include <WNS/ldk/Layer.hpp> 00034 #include <WNS/ldk/crc/CRC.hpp> 00035 #include <WNS/probe/bus/utils.hpp> 00036 00037 #include <DLL/Layer2.hpp> 00038 00039 using namespace wimemac::convergence; 00040 00041 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00042 FrameSynchronization, 00043 wns::ldk::probe::Probe, 00044 "wimemac.convergence.FrameSynchronization", 00045 wns::ldk::FUNConfigCreator); 00046 00047 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00048 FrameSynchronization, 00049 wns::ldk::FunctionalUnit, 00050 "wimemac.convergence.FrameSynchronization", 00051 wns::ldk::FUNConfigCreator); 00052 00053 FrameSynchronization::FrameSynchronization(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config): 00054 wns::ldk::fu::Plain<FrameSynchronization, FrameSynchronizationCommand>(fun), 00055 wns::ldk::probe::Probe(), 00056 00057 logger(config.get("logger")), 00058 curState(Idle), 00059 synchronizedToAddress(), 00060 slcCapture(config.get<wns::Ratio>("myConfig.slcCapture")), 00061 slgCapture(config.get<wns::Ratio>("myConfig.slgCapture")), 00062 idleCapture(config.get<wns::Ratio>("myConfig.idleCapture")), 00063 detectionThreshold(config.get<wns::Ratio>("myConfig.detectionThreshold")), 00064 signalRxErrorAlthoughNotSynchronized(config.get<bool>("myConfig.signalRxErrorAlthoughNotSynchronized")), 00065 lastFrameEnd(0), 00066 managerName(config.get<std::string>("managerName")), 00067 crcCommandName(config.get<std::string>("crcCommandName")) 00068 { 00069 // read the localIDs from the config 00070 wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection()); 00071 for (int ii = 0; ii<config.len("localIDs.keys()"); ++ii) 00072 { 00073 std::string key = config.get<std::string>("localIDs.keys()",ii); 00074 unsigned long int value = config.get<unsigned long int>("localIDs.values()",ii); 00075 localContext.addProvider(wns::probe::bus::contextprovider::Constant(key, value)); 00076 MESSAGE_SINGLE(VERBOSE, logger, "Using Local IDName '"<<key<<"' with value: "<<value); 00077 } 00078 00079 } 00080 00081 FrameSynchronization::~FrameSynchronization() 00082 { 00083 00084 } 00085 00086 void FrameSynchronization::doSendData(const wns::ldk::CompoundPtr& compound) 00087 { 00088 // Stop any synchronization 00089 switch(curState) 00090 { 00091 case Idle: 00092 break; 00093 case Synchronized: 00094 // signal end of frame to each observer 00095 MESSAGE_SINGLE(NORMAL, logger, "Send data during decoding -> signal rx error"); 00096 this->wns::Subject<IRxStartEnd>::forEachObserver(OnRxStartEnd(0, false, true)); 00097 // Fall through to set state to Idle 00098 case waitForFinalDelivery: 00099 case Garbled: 00100 MESSAGE_SINGLE(NORMAL, logger, "Send data during reception -> reset curState to idle"); 00101 lastFrameEnd = wns::simulator::getEventScheduler()->getTime(); 00102 if(hasTimeoutSet()) 00103 cancelTimeout(); 00104 curState = Idle; 00105 synchronizedToAddress = wns::service::dll::UnicastAddress(); 00106 break; 00107 default: 00108 assure(false, "Unknown state"); 00109 } 00110 00111 // pass through 00112 getConnector()->getAcceptor(compound)->sendData(compound); 00113 } 00114 00115 void FrameSynchronization::doOnData(const wns::ldk::CompoundPtr& compound) 00116 { 00117 if(friends.manager->isPreamble(compound->getCommandPool())) 00118 { 00119 this->processPreamble(compound); 00120 } 00121 else 00122 { 00123 this->processPSDU(compound); 00124 } 00125 } 00126 00127 void FrameSynchronization::processPreamble(const wns::ldk::CompoundPtr& compound) 00128 { 00129 assure(friends.manager->isPreamble(compound->getCommandPool()), 00130 "called processPreamble for non-preamble"); 00131 00132 bool crcOk = getFUN()->getCommandReader(crcCommandName)->readCommand<wimemac::convergence::ErrorModellingCommand>(compound->getCommandPool())->local.checkOK; 00133 00134 wns::simulator::Time fDur = friends.manager->getpsduDuration(compound->getCommandPool()); 00135 if(!friends.manager->hasPayload(compound->getCommandPool())) fDur = 0; 00136 00137 wns::Ratio sinr = getFUN()->getCommandReader(crcCommandName)->readCommand<wimemac::convergence::ErrorModellingCommand>(compound->getCommandPool())->local.sinr; 00138 00139 if(sinr < detectionThreshold) 00140 { 00141 MESSAGE_SINGLE(NORMAL, logger, "ProcessPreamble(idle), SINR= " << sinr << " below detection threshold -> DROP"); 00142 return; 00143 } 00144 00145 wns::Ratio captureThreshold; 00146 switch(curState) 00147 { 00148 case Idle: 00149 MESSAGE_SINGLE(NORMAL, logger, "ProcessPreamble(idle), SINR= " << sinr << " CRC " << crcOk); 00150 assure(lastFrameEnd <= wns::simulator::getEventScheduler()->getTime(), "State is idle, but last frame has not finished"); 00151 assure(!this->hasTimeoutSet(), "State is idle, but timeout is set"); 00152 captureThreshold = idleCapture; 00153 break; 00154 00155 case Synchronized: 00156 MESSAGE_SINGLE(NORMAL, logger, "processPreamble(synchronized), SINR= " << sinr << " CRC " << crcOk); 00157 assure(lastFrameEnd >= wns::simulator::getEventScheduler()->getTime(), "State is synchronized, but lastFrameEnd is over"); 00158 assure(this->hasTimeoutSet(), "State is decoding, but no timeout set"); 00159 captureThreshold = slcCapture; 00160 break; 00161 00162 case waitForFinalDelivery: 00163 MESSAGE_SINGLE(NORMAL, logger, "processPreamble(waitForFinalDelivery), SINR= " << sinr << " CRC " << crcOk); 00164 assure(this->hasTimeoutSet(), "State is waitForFinalDelivery, but no timeout set"); 00165 assure(lastFrameEnd+10e-9 >= wns::simulator::getEventScheduler()->getTime(), "State is waitForFinalDelivery, but lastFrameEnd is over"); 00166 captureThreshold = slcCapture; 00167 break; 00168 00169 case Garbled: 00170 MESSAGE_SINGLE(NORMAL, logger, "processPreamble(garbled), SINR= " << sinr << " CRC " << crcOk); 00171 assure(this->hasTimeoutSet(), "State is garbled, but no timeout set"); 00172 assure(lastFrameEnd >= wns::simulator::getEventScheduler()->getTime(), "State is garbled, but lastFrameEnd is over"); 00173 captureThreshold = slgCapture; 00174 break; 00175 00176 default: 00177 assure(false, "Unknown state"); 00178 } 00179 00180 if (sinr > captureThreshold) 00181 { 00182 // capture has taken place 00183 if(curState == Synchronized) 00184 { 00185 // signal end of frame to each observer 00186 MESSAGE_SINGLE(NORMAL, logger, "ProcessPreamble -> Capture current decoding, signal rx end"); 00187 this->wns::Subject<IRxStartEnd>::forEachObserver(OnRxStartEnd(0, false, true)); 00188 } 00189 00190 if(crcOk) 00191 { 00192 // if(friends.manager->hasPayload(compound->getCommandPool())) 00193 // { 00194 this->syncToNewPreamble(fDur, friends.manager->getTransmitterAddress(compound->getCommandPool())); 00195 // } 00196 // else 00197 // { 00198 // if((wns::simulator::getEventScheduler()->getTime()) > lastFrameEnd) 00199 // { 00200 // // only change lastFrameEnd if the new frame is longer than the current one 00201 // lastFrameEnd = wns::simulator::getEventScheduler()->getTime(); 00202 // MESSAGE_SINGLE(NORMAL, logger, "Rx preamble without payload, sync ended " << lastFrameEnd); 00203 // } 00204 // else 00205 // { 00206 // MESSAGE_SINGLE(NORMAL, logger, "Rx preamble without payload, sync ended " << wns::simulator::getEventScheduler()->getTime() << ", afterwards garbled until " << lastFrameEnd); 00207 // } 00208 // } 00209 00210 // deliver preamble 00211 getDeliverer()->getAcceptor(compound)->onData(compound); 00212 } 00213 else 00214 { 00215 this->failedSyncToNewPreamble(fDur); 00216 } 00217 } 00218 else 00219 { 00220 if ((curState == Synchronized) or (curState == waitForFinalDelivery)) 00221 { 00222 // special handling if the state is synchronized: 00223 // Wait for the end of the current frame, and then change into the garbled state if neccessary 00224 if(wns::simulator::getEventScheduler()->getTime() + fDur > lastFrameEnd) 00225 { 00226 lastFrameEnd = wns::simulator::getEventScheduler()->getTime() + fDur; 00227 MESSAGE_SINGLE(NORMAL, logger, "Rx preamble while synchronized, but no capture, decode frame and then garbled until " << lastFrameEnd); 00228 } 00229 else 00230 { 00231 MESSAGE_SINGLE(NORMAL, logger, "Rx preamble while synchronized, no capture, frame is shorter than current one"); 00232 } 00233 } 00234 else 00235 { 00236 this->failedSyncToNewPreamble(fDur); 00237 } 00238 } 00239 } 00240 00241 void FrameSynchronization::failedSyncToNewPreamble(wns::simulator::Time fDur) 00242 { 00243 if((wns::simulator::getEventScheduler()->getTime() + fDur) >= lastFrameEnd) 00244 { 00245 lastFrameEnd = wns::simulator::getEventScheduler()->getTime() + fDur; 00246 this->setNewTimeout(fDur); 00247 MESSAGE_SINGLE(NORMAL, logger, "Rx preamble, but no sync possible -> garbled until " << lastFrameEnd); 00248 } 00249 else 00250 { 00251 assure(this->hasTimeoutSet(), "lastFrameEnd is not over, but no timeout set"); 00252 MESSAGE_SINGLE(NORMAL, logger, "Rx another preamble, but no sync possible -> garbled for " << fDur << " and afterwards until " << lastFrameEnd); 00253 } 00254 this->synchronizedToAddress = wns::service::dll::UnicastAddress(); 00255 curState = Garbled; 00256 } 00257 00258 void FrameSynchronization::syncToNewPreamble(const wns::simulator::Time fDur, const wns::service::dll::UnicastAddress transmitter) 00259 { 00260 //MESSAGE_SINGLE(NORMAL, logger, "Rx preamble, signal rxStart"); 00261 //assure(fDur > 0, "Preamble must have duration larger than zero"); 00262 if (fDur > 0) 00263 { 00264 this->wns::Subject<IRxStartEnd>::forEachObserver(OnRxStartEnd(fDur, true, false)); 00265 00266 this->setNewTimeout(fDur); 00267 if((wns::simulator::getEventScheduler()->getTime() + fDur) > lastFrameEnd) 00268 { 00269 // only change lastFrameEnd if the new frame is longer than the current one 00270 lastFrameEnd = wns::simulator::getEventScheduler()->getTime() + fDur; 00271 MESSAGE_SINGLE(NORMAL, logger, "Rx preamble, synced until " << lastFrameEnd); 00272 } 00273 else 00274 { 00275 MESSAGE_SINGLE(NORMAL, logger, "Rx preamble, synced for " << fDur << ", afterwards garbled until " << lastFrameEnd); 00276 } 00277 this->synchronizedToAddress = transmitter; 00278 curState = Synchronized; 00279 } 00280 else MESSAGE_SINGLE(NORMAL, logger, "Rx preamble without payload, rx already ended"); 00281 } 00282 00283 void FrameSynchronization::onTimeout() 00284 { 00285 if(curState == Synchronized) 00286 { 00287 // finished reception 00288 MESSAGE_SINGLE(NORMAL, logger, "End of decoding, signal rxEnd"); 00289 this->wns::Subject<IRxStartEnd>::forEachObserver(OnRxStartEnd(0, false, false)); 00290 curState = waitForFinalDelivery; 00291 setTimeout(10e-9); 00292 return; 00293 } 00294 00295 // Frame reception as indicated by the preamble is over, stop synchronization 00296 if(lastFrameEnd > wns::simulator::getEventScheduler()->getTime()) 00297 { 00298 // there are still active transmissions, but the preamble was missed 00299 curState = Garbled; 00300 this->setTimeout(lastFrameEnd-wns::simulator::getEventScheduler()->getTime()); 00301 MESSAGE_SINGLE(NORMAL, logger, "End of frame, change state to garbled until " << lastFrameEnd); 00302 } 00303 else 00304 { 00305 MESSAGE_SINGLE(NORMAL, logger, "End of frame, change state to idle"); 00306 curState = Idle; 00307 } 00308 this->synchronizedToAddress = wns::service::dll::UnicastAddress(); 00309 } 00310 00311 void FrameSynchronization::processPSDU(const wns::ldk::CompoundPtr& compound) 00312 { 00313 assure(!friends.manager->isPreamble(compound->getCommandPool()), 00314 "called processPSDU for non-psdu"); 00315 00316 MESSAGE_BEGIN(NORMAL, logger, m, ""); 00317 m << "Received psdu. Synchronized: " << (curState == Synchronized or curState == waitForFinalDelivery); 00318 m << "; Transmitter ok: " << (friends.manager->getTransmitterAddress(compound->getCommandPool()) == this->synchronizedToAddress); 00319 m << "; CRC ok: " << (getFUN()->getCommandReader(crcCommandName)-> 00320 readCommand<wimemac::convergence::ErrorModellingCommand>(compound->getCommandPool())-> 00321 local.checkOK); 00322 MESSAGE_END(); 00323 00324 wns::Ratio sinr = getFUN()->getCommandReader(crcCommandName)->readCommand<wimemac::convergence::ErrorModellingCommand>(compound->getCommandPool())->local.sinr; 00325 00326 if((curState == Synchronized or curState == waitForFinalDelivery) and 00327 (friends.manager->getTransmitterAddress(compound->getCommandPool()) == this->synchronizedToAddress)) 00328 { 00329 if(getFUN()->getCommandReader(crcCommandName)->readCommand<wimemac::convergence::ErrorModellingCommand>(compound->getCommandPool())->local.checkOK) 00330 { 00331 MESSAGE_SINGLE(NORMAL, logger, "Received matching psdu for current synchronization"); 00332 getDeliverer()->getAcceptor(compound)->onData(compound); 00333 } 00334 else 00335 { 00336 MESSAGE_SINGLE(NORMAL, logger, "Received (synchronized) psdu, but CRC error -> DROP"); 00337 // Signal rxError event 00338 this->wns::Subject<IRxStartEnd>::forEachObserver(OnRxStartEnd(0, false, true)); 00339 } 00340 } 00341 else 00342 { 00343 MESSAGE_SINGLE(NORMAL, logger, "Received psdu, but not synchronized -> DROP"); 00344 // signal rxError only in case the user specifically asked for this kind 00345 // of strange behavior (i.e. not synchronized --> CRC cannot be checked 00346 // at all! 00347 if(this->signalRxErrorAlthoughNotSynchronized) 00348 { 00349 this->wns::Subject<IRxStartEnd>::forEachObserver(OnRxStartEnd(0, false, true)); 00350 } 00351 } 00352 00353 // delivery occured 00354 if((curState == waitForFinalDelivery) and (friends.manager->getTransmitterAddress(compound->getCommandPool()) == this->synchronizedToAddress)) 00355 { 00356 assure(hasTimeoutSet(), "State is waitForFinalDelivery, but no timeout set"); 00357 cancelTimeout(); 00358 onTimeout(); 00359 } 00360 } 00361 00362 void FrameSynchronization::onFUNCreated() 00363 { 00364 friends.manager = getFUN()->findFriend<wimemac::lowerMAC::IManagerServices*>(managerName); 00365 } 00366 00367 bool FrameSynchronization::doIsAccepting(const wns::ldk::CompoundPtr& compound) const 00368 { 00369 return getConnector()->hasAcceptor(compound); 00370 } 00371 00372 void FrameSynchronization::doWakeup() 00373 { 00374 getReceptor()->wakeup(); 00375 }
1.5.5