![]() |
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/PhyMode.hpp> 00030 #include <WIMEMAC/convergence/ErrorModelling.hpp> 00031 #include <WIMEMAC/lowerMAC/Manager.hpp> 00032 #include "IPhyServices.hpp" 00033 00034 using namespace wimemac::convergence; 00035 00036 STATIC_FACTORY_REGISTER_WITH_CREATOR( 00037 wimemac::convergence::ErrorModelling, 00038 wns::ldk::FunctionalUnit, 00039 "wimemac.convergence.ErrorModelling", 00040 wns::ldk::FUNConfigCreator); 00041 00042 00043 ErrorModelling::ErrorModelling(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& _config) : 00044 wns::ldk::fu::Plain<ErrorModelling, ErrorModellingCommand>(fun), 00045 config(_config), 00046 logger(config.get<wns::pyconfig::View>("logger")), 00047 phyUserCommandName(config.get<std::string>("phyUserCommandName")), 00048 phyUserName(config.get<std::string>("phyUserName")), 00049 managerName(config.get<std::string>("managerName")), 00050 managerCommandName(config.get<std::string>("managerCommandName")), 00051 dis(), 00052 perProbe_(new wns::probe::bus::ContextCollector(wns::probe::bus::ContextProviderCollection(&fun->getLayer()->getContextProviderCollection()), "wimemac.errormodelling.PER")) 00053 { 00054 00055 // read the localIDs from the config 00056 wns::probe::bus::ContextProviderCollection localContext(&fun->getLayer()->getContextProviderCollection()); 00057 00058 for (int ii = 0; ii<config.len("localIDs.keys()"); ++ii) 00059 { 00060 std::string key = config.get<std::string>("localIDs.keys()",ii); 00061 unsigned long int value = config.get<unsigned long int>("localIDs.values()",ii); 00062 localContext.addProvider( wns::probe::bus::contextprovider::Constant(key, value) ); 00063 } 00064 00065 lossRatio = wns::probe::bus::collector(localContext, config, "lossRatioProbeName"); 00066 00067 00068 // Fill the error mapping from the config 00069 wns::pyconfig::View configview = config.getView("snr2pmean_100"); 00070 for(int i = 0; i < configview.len("mapping"); ++i) 00071 { 00072 wns::pyconfig::View mo = configview.getView("mapping", i); 00073 if(i == (configview.len("mapping") - 1)) 00074 { 00075 snr2pmean_100_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00076 } 00077 else 00078 { 00079 if(i == 0) 00080 { 00081 snr2pmean_100_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00082 } 00083 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00084 snr2pmean_100_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00085 } 00086 } 00087 00088 configview = config.getView("snr2pmean_150"); 00089 for(int i = 0; i < configview.len("mapping"); ++i) 00090 { 00091 wns::pyconfig::View mo = configview.getView("mapping", i); 00092 if(i == (configview.len("mapping") - 1)) 00093 { 00094 snr2pmean_150_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00095 } 00096 else 00097 { 00098 if(i == 0) 00099 { 00100 snr2pmean_150_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00101 } 00102 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00103 snr2pmean_150_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00104 } 00105 } 00106 00107 configview = config.getView("snr2pmean_200"); 00108 for(int i = 0; i < configview.len("mapping"); ++i) 00109 { 00110 wns::pyconfig::View mo = configview.getView("mapping", i); 00111 if(i == (configview.len("mapping") - 1)) 00112 { 00113 snr2pmean_200_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00114 } 00115 else 00116 { 00117 if(i == 0) 00118 { 00119 snr2pmean_200_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00120 } 00121 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00122 snr2pmean_200_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00123 } 00124 } 00125 00126 configview = config.getView("snr2pmean_300"); 00127 for(int i = 0; i < configview.len("mapping"); ++i) 00128 { 00129 wns::pyconfig::View mo = configview.getView("mapping", i); 00130 if(i == (configview.len("mapping") - 1)) 00131 { 00132 snr2pmean_300_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00133 } 00134 else 00135 { 00136 if(i == 0) 00137 { 00138 snr2pmean_300_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00139 } 00140 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00141 snr2pmean_300_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00142 } 00143 } 00144 00145 configview = config.getView("snr2pmean_375"); 00146 for(int i = 0; i < configview.len("mapping"); ++i) 00147 { 00148 wns::pyconfig::View mo = configview.getView("mapping", i); 00149 if(i == (configview.len("mapping") - 1)) 00150 { 00151 snr2pmean_375_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00152 } 00153 else 00154 { 00155 if(i == 0) 00156 { 00157 snr2pmean_375_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00158 } 00159 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00160 snr2pmean_375_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00161 } 00162 } 00163 00164 configview = config.getView("snr2pmean_600"); 00165 for(int i = 0; i < configview.len("mapping"); ++i) 00166 { 00167 wns::pyconfig::View mo = configview.getView("mapping", i); 00168 if(i == (configview.len("mapping") - 1)) 00169 { 00170 snr2pmean_600_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00171 } 00172 else 00173 { 00174 if(i == 0) 00175 { 00176 snr2pmean_600_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00177 } 00178 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00179 snr2pmean_600_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00180 } 00181 } 00182 00183 00184 configview = config.getView("snr2pmean_750"); 00185 for(int i = 0; i < configview.len("mapping"); ++i) 00186 { 00187 wns::pyconfig::View mo = configview.getView("mapping", i); 00188 if(i == (configview.len("mapping") - 1)) 00189 { 00190 snr2pmean_750_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00191 } 00192 else 00193 { 00194 if(i == 0) 00195 { 00196 snr2pmean_750_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00197 } 00198 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00199 snr2pmean_750_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00200 } 00201 } 00202 00203 configview = config.getView("snr2pmean_900"); 00204 for(int i = 0; i < configview.len("mapping"); ++i) 00205 { 00206 wns::pyconfig::View mo = configview.getView("mapping", i); 00207 if(i == (configview.len("mapping") - 1)) 00208 { 00209 snr2pmean_900_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(100), mo.get<float>("pmean")); 00210 } 00211 else 00212 { 00213 if(i == 0) 00214 { 00215 snr2pmean_900_.insert(SNR2PmeanMap::IntervalType::FromIncluding(-10).ToExcluding(mo.get<float>("snr")), 1); 00216 } 00217 wns::pyconfig::View nextMo = configview.getView("mapping", i+1); 00218 snr2pmean_900_.insert(SNR2PmeanMap::IntervalType::FromIncluding(mo.get<float>("snr")).ToExcluding(nextMo.get<float>("snr")), mo.get<float>("pmean")); 00219 } 00220 } 00221 } 00222 00223 void ErrorModelling::onFUNCreated() 00224 { 00225 friends.phyuser = getFUN()->findFriend<wimemac::convergence::IPhyServices*>(phyUserName); 00226 friends.manager = getFUN()->findFriend<wimemac::lowerMAC::IManagerServices*>(managerName); 00227 00228 // Fill the registry with the snr2pmean maps together with their corresponding phymodes as key 00229 // get lowest phymode and start filling the registry 00230 wimemac::convergence::PhyMode phyMode_ = friends.phyuser->getPhyModeProvider()->getPreamblePhyMode(friends.phyuser->getPhyModeProvider()->getDefaultPhyMode()); 00231 assure(friends.phyuser->getPhyModeProvider()->hasLowestMCS(phyMode_), "Couldn't retrieve the lowest MCS"); 00232 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_100_); 00233 00234 // get the next higher MCS and proceed 00235 friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00236 assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined"); 00237 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_150_); 00238 00239 // get the next higher MCS and proceed 00240 friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00241 assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined"); 00242 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_200_); 00243 00244 // get the next higher MCS and proceed 00245 friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00246 assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined"); 00247 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_300_); 00248 00249 // get the next higher MCS and proceed 00250 friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00251 assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined"); 00252 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_375_); 00253 00254 // get the next higher MCS and proceed 00255 friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00256 assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined"); 00257 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_600_); 00258 00259 // get the next higher MCS and proceed 00260 friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00261 assure(!friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too less MCSs defined"); 00262 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_750_); 00263 00264 // get the next higher MCS and proceed 00265 friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00266 assure(friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_), "There are too many MCSs defined"); 00267 snr2pmeanReg_.insert(phyMode_.getMCS(), &snr2pmean_900_); 00268 } 00269 00270 void ErrorModelling::processIncoming(const wns::ldk::CompoundPtr& compound) 00271 { 00272 00273 // Calculate PER 00274 00275 wns::Power rxPower_ = friends.phyuser->getRxPower(compound->getCommandPool()); 00276 wns::Power interference_ = friends.phyuser->getInterference(compound->getCommandPool()); 00277 00278 wns::Ratio sinr_ = wns::Ratio::from_dB(rxPower_.get_dBm() - interference_.get_dBm()); 00279 00280 //MESSAGE_BEGIN(NORMAL, logger, m, "DEBUG : Errormodelling " << sinr_); 00281 //m << " | rx " << rxPower_; 00282 //m << " | interference " << interference_; 00283 //MESSAGE_END(); 00284 00285 wimemac::convergence::PhyMode phyMode_ = friends.manager->getPhyMode(compound->getCommandPool()); 00286 00287 ErrorModellingCommand* emc = activateCommand(compound->getCommandPool()); 00288 emc->local.sinr = sinr_; 00289 00290 float pmean_ = NULL; 00291 00292 SNR2PmeanMap* snr2pmeanMap_ = snr2pmeanReg_.find(phyMode_.getMCS()); 00293 00294 if (!snr2pmeanMap_->has(float(sinr_.get_dB()))) 00295 { 00296 if(sinr_.get_dB() < -10) pmean_ = 0; 00297 else if(sinr_.get_dB() > 100) pmean_ = snr2pmeanMap_->get(float(sinr_.get_dB())); 00298 else 00299 { 00300 // Needed to prevent rangemap bug if asking for an INT value 00301 MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR before" << sinr_.get_dB()); 00302 sinr_.set_dB(sinr_.get_dB() + 0.001); 00303 MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR after" << sinr_.get_dB()); 00304 } 00305 } 00306 else pmean_ = snr2pmeanMap_->get(float(sinr_.get_dB())); 00307 00308 // get frame length; check if compound is preamble or psdu 00309 Bit compsize_ = compound->getLengthInBits(); 00310 00311 double q = 1 / (pmean_ - 7 + 2); // K = 7 is constraint length of the convolutional code 00312 if (pmean_ - 7 + 2 <= 0) q = 1; 00313 emc->local.per = 1 - pow( (1 - q), (compsize_-(7-1)) ); 00314 00315 // If rxPower is below the minimum rxPower set PER = 1 00316 if (rxPower_ < friends.manager->getPhyMode(compound->getCommandPool()).getMinRxPower()) 00317 emc->local.per = 1; 00318 00319 // Put per into probe if it's a payload compound 00320 if (!friends.manager->isPreamble(compound->getCommandPool()) && 00321 !friends.manager->isBeacon(compound->getCommandPool()) && 00322 friends.manager->isForMe(compound->getCommandPool())) 00323 perProbe_->put(compound, emc->local.per); 00324 00325 00326 wns::service::dll::UnicastAddress tx = friends.manager->getTransmitterAddress(compound->getCommandPool()); 00327 MESSAGE_BEGIN(NORMAL, logger, m, "New compound with SNR " << sinr_); 00328 m << " | CompSize " << compsize_; 00329 m << " | NIBP6S " << phyMode_.getInfoBitsPer6Symbols(); 00330 m << " | Pmean " << pmean_; 00331 m << " | PER " << emc->local.per; 00332 m << " | from address " << tx; 00333 MESSAGE_END(); 00334 00335 // Mark compound according to per evaluation 00336 if(!lastPreambleWasDecoded.knows(tx)) lastPreambleWasDecoded.insert(tx, false); 00337 if ( dis() < emc->local.per ){ 00338 00339 if (lossRatio != NULL) 00340 { 00341 lossRatio->put(compound, 1); 00342 } 00343 emc->local.checkOK = false; 00344 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00345 m << " CRCheck - failed - compound marked"; 00346 MESSAGE_END(); 00347 00348 if (friends.manager->isPreamble(compound->getCommandPool())) 00349 lastPreambleWasDecoded.update(tx, false); 00350 } 00351 else 00352 { 00353 if (friends.manager->isPreamble(compound->getCommandPool())) 00354 { 00355 lastPreambleWasDecoded.update(tx, true); 00356 emc->local.checkOK = true; 00357 } 00358 else 00359 { 00360 // Check if before received preamble could be decoded, otherwise mark payload compound as bad 00361 if(lastPreambleWasDecoded.find(tx) == true) 00362 { 00363 emc->local.checkOK = true; 00364 if (lossRatio != NULL) 00365 { 00366 lossRatio->put(compound, 0); 00367 } 00368 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00369 m << " CRCheck - success"; 00370 MESSAGE_END(); 00371 00372 } 00373 else 00374 { 00375 emc->local.checkOK = false; 00376 if (lossRatio != NULL) 00377 { 00378 lossRatio->put(compound, 1); 00379 } 00380 MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00381 m << " CRCheck - failed because of bad preamble - compound marked"; 00382 MESSAGE_END(); 00383 } 00384 } 00385 00386 } 00387 00388 } 00389 00390 void ErrorModelling::processOutgoing(const wns::ldk::CompoundPtr& /*compound*/) 00391 { 00392 //MESSAGE_BEGIN(NORMAL, logger, m, getFUN()->getName()); 00393 //m << " passing through Errormodelling outgoing"; 00394 //MESSAGE_END(); 00395 } 00396 00397 wimemac::convergence::MCS 00398 ErrorModelling::getMaxPosMCS(wns::Ratio sinr_, Bit maxCompoundSize_, double per_) 00399 { 00400 // Calculate minimum allowed pmean 00401 double pow_ = pow( (1-per_) , (1 / ((double)maxCompoundSize_ - 7 + 1)) ); 00402 float pmean_ = 7 - 2 + 1 / ( 1 - pow_ ); 00403 00404 // Search through the mapping registry for the highest MCS with a pmean greater than the calculated one 00405 wimemac::convergence::PhyMode phyMode_ = friends.phyuser->getPhyModeProvider()->getPreamblePhyMode(friends.phyuser->getPhyModeProvider()->getDefaultPhyMode()); 00406 assure(friends.phyuser->getPhyModeProvider()->hasLowestMCS(phyMode_), "Couldn't retrieve the lowest MCS"); 00407 00408 bool foundMax_ = false; 00409 while (!foundMax_) 00410 { 00411 SNR2PmeanMap* snr2pmeanMap_ = snr2pmeanReg_.find(phyMode_.getMCS()); 00412 // Check if pmean for this MCS and SNR is greater than the min pmean 00413 00414 float pmeanMapped_; 00415 if (!snr2pmeanMap_->has(float(sinr_.get_dB()))) 00416 { 00417 if(sinr_.get_dB() < -10) pmeanMapped_ = 0; 00418 else if(sinr_.get_dB() > 100) pmeanMapped_ = snr2pmeanMap_->get(float(sinr_.get_dB())); 00419 // Needed to prevent rangemap bug if asking for an INT value 00420 sinr_.set_dB(sinr_.get_dB() + 0.001); 00421 MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR after" << sinr_.get_dB()); 00422 } 00423 else pmeanMapped_ = snr2pmeanMap_->get(float(sinr_.get_dB())); 00424 00425 if(pmean_ <= pmeanMapped_) 00426 { 00427 // Is the maximum MCS reached -> use this 00428 if(friends.phyuser->getPhyModeProvider()->hasHighestMCS(phyMode_)) 00429 { 00430 foundMax_ = true; 00431 } 00432 // Increment MCS to check if next one also meets the min pmean 00433 else friends.phyuser->getPhyModeProvider()->mcsUp(phyMode_); 00434 } 00435 else 00436 { 00437 // The MCS did not meet the requirements -> use next lower MCS 00438 if (friends.phyuser->getPhyModeProvider()->hasLowestMCS(phyMode_)) 00439 { 00440 MESSAGE_SINGLE(NORMAL, logger, "LinkEval : Even lowest PhyMode is not sufficient! Returning lowest MCS to proceed"); 00441 } 00442 else friends.phyuser->getPhyModeProvider()->mcsDown(phyMode_); 00443 foundMax_ = true; 00444 } 00445 } 00446 00447 // MESSAGE_SINGLE(NORMAL, logger, "Calculate MaxMCS : " <<" Returning Phymode with "<< phyMode_.getDataRate() << " MBit/s" ); 00448 return phyMode_.getMCS(); 00449 } 00450 00451 double 00452 ErrorModelling::getErrorRateForCommandFrames(wns::Ratio sinr_, Bit maxCompoundSize_) 00453 { 00454 00455 float pmean; 00456 wimemac::convergence::PhyMode phyMode_ = friends.phyuser->getPhyModeProvider()->getPreamblePhyMode(); 00457 SNR2PmeanMap* snr2pmeanMap_ = snr2pmeanReg_.find(phyMode_.getMCS()); 00458 00459 if (!snr2pmeanMap_->has(float(sinr_.get_dB()))) 00460 { 00461 if(sinr_.get_dB() < -10) pmean = 0; 00462 else if(sinr_.get_dB() > 100) pmean = snr2pmeanMap_->get(float(sinr_.get_dB())); 00463 else 00464 { 00465 // Needed to prevent rangemap bug if asking for an INT value 00466 MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR before" << sinr_.get_dB()); 00467 sinr_.set_dB(sinr_.get_dB() + 0.001); 00468 MESSAGE_SINGLE(NORMAL, logger, "DEBUG: SINR after" << sinr_.get_dB()); 00469 } 00470 } 00471 else pmean = snr2pmeanMap_->get(float(sinr_.get_dB())); 00472 00473 double q = 1 / (pmean - 7 + 2); // K = 7 is constraint length of the convolutional code 00474 if (pmean - 7 + 2 <= 0) q = 1; 00475 return(1 - pow( (1 - q), (maxCompoundSize_-(7-1)) )); 00476 }
1.5.5