SNRThresholdDecider.cc

00001 #include "SNRThresholdDecider.h"
00002 
00003 simtime_t SNRThresholdDecider::processNewSignal(AirFrame* frame)
00004 {
00005   //the rssi level changes therefore we need to check if we can
00006   //answer an ongoing ChannelSenseRequest now
00007   channelStateChanged();
00008 
00009   if(currentSignal.first != 0) {
00010     deciderEV << "Already receiving another AirFrame!" << endl;
00011     return notAgain;
00012   }
00013 
00014   //get the receiving power of the Signal
00015   //Note: We assume the transmission power is represented by a rectangular function
00016   //which discontinuities (at start and end of the signal) are represented
00017   //by two key entries with different values very close to each other (see
00018   //MappingUtils "addDiscontinuity" method for details). This means
00019   //the transmission- and therefore also the receiving-power-mapping is still zero
00020   //at the exact start of the signal and not till one time step after the start its
00021   //at its actual transmission(/receiving) power.
00022   //Therefore we use MappingUtils "post"-method to ask for the receiving power
00023   //at the correct position.
00024   Signal& signal = frame->getSignal();
00025   simtime_t receivingStart = MappingUtils::post(signal.getSignalStart());
00026   double recvPower = signal.getReceivingPower()->getValue(Argument(receivingStart));
00027 
00028   // check whether signal is strong enough to receive
00029   if ( recvPower < sensitivity )
00030   {
00031     deciderEV << "Signal is to weak (" << recvPower << " < " << sensitivity
00032         << ") -> do not receive." << endl;
00033     // Signal too weak, we can't receive it, tell PhyLayer that we don't want it again
00034     return notAgain;
00035   }
00036 
00037   // Signal is strong enough, receive this Signal and schedule it
00038   deciderEV << "Signal is strong enough (" << recvPower << " > " << sensitivity
00039       << ") -> Trying to receive AirFrame." << endl;
00040 
00041   currentSignal.first = frame;
00042   currentSignal.second = EXPECT_END;
00043 
00044   return ( signal.getSignalStart() + signal.getSignalLength() );
00045 }
00046 
00047 // TODO: for now we check a larger mapping within an interval
00048 bool SNRThresholdDecider::checkIfAboveThreshold(Mapping* map, simtime_t start, simtime_t end)
00049 {
00050   assert(map);
00051 
00052   if(debug){
00053     deciderEV << "Checking if SNR is above Threshold of " << snrThreshold << endl;
00054   }
00055 
00056   // check every entry in the mapping against threshold value
00057   ConstMappingIterator* it = map->createConstIterator(Argument(start));
00058   // check if values at start-time fulfill snrThreshold-criterion
00059   if(debug){
00060     deciderEV << "SNR at time " << start << " is " << it->getValue() << endl;
00061   }
00062   if ( it->getValue() <= snrThreshold ){
00063     delete it;
00064     return false;
00065   }
00066 
00067   while ( it->hasNext() && it->getNextPosition().getTime() < end)
00068   {
00069     it->next();
00070 
00071     if(debug){
00072       deciderEV << "SNR at time " << it->getPosition().getTime() << " is " << it->getValue() << endl;
00073     }
00074 
00075     // perform the check for smaller entry
00076     if ( it->getValue() <= snrThreshold) {
00077       delete it;
00078       return false;
00079     }
00080   }
00081 
00082   it->iterateTo(Argument(end));
00083   if(debug){
00084     deciderEV << "SNR at time " << end << " is " << it->getValue() << endl;
00085   }
00086 
00087   if ( it->getValue() <= snrThreshold ){
00088     delete it;
00089     return false;
00090   }
00091 
00092   delete it;
00093   return true;
00094 }
00095 
00096 ChannelState SNRThresholdDecider::getChannelState() {
00097 
00098   simtime_t now = phy->getSimTime();
00099   double rssiValue = calcChannelSenseRSSI(now, now);
00100 
00101   return ChannelState(isIdleRSSI(rssiValue), rssiValue);
00102 }
00103 
00104 void SNRThresholdDecider::answerCSR(CSRInfo& requestInfo)
00105 {
00106   // put the sensing-result to the request and
00107   // send it to the Mac-Layer as Control-message (via Interface)
00108   requestInfo.first->setResult( getChannelState() );
00109   phy->sendControlMsg(requestInfo.first);
00110 
00111   requestInfo.first = 0;
00112   requestInfo.second = -1;
00113   requestInfo.canAnswerAt = -1;
00114 }
00115 
00116 simtime_t SNRThresholdDecider::canAnswerCSR(const CSRInfo& requestInfo) {
00117   const ChannelSenseRequest* request = requestInfo.getRequest();
00118   assert(request);
00119 
00120   if(request->getSenseMode() == UNTIL_TIMEOUT) {
00121     opp_error("SNRThresholdDecider received an UNTIL_TIMEOUT ChannelSenseRequest.\n"
00122           "SNRThresholdDecider can only handle UNTIL_IDLE or UNTIL_BUSY requests because it "
00123           "implements only instantaneous sensing where UNTIL_TIMEOUT requests "
00124           "don't make sense. Please refer to ChannelSenseRequests documentation "
00125           "for details.");
00126   }
00127 
00128   simtime_t requestTimeout = requestInfo.getSenseStart() + request->getSenseTimeout();
00129 
00130   simtime_t now = phy->getSimTime();
00131 
00132   ConstMapping* rssiMapping = calculateRSSIMapping(now, requestTimeout);
00133 
00134   //this Decider only works for time-only signals
00135   assert(rssiMapping->getDimensionSet() == DimensionSet::timeDomain);
00136 
00137   ConstMappingIterator* it = rssiMapping->createConstIterator(Argument(now));
00138 
00139   assert(request->getSenseMode() == UNTIL_IDLE
00140        || request->getSenseMode() == UNTIL_BUSY);
00141   bool untilIdle = request->getSenseMode() == UNTIL_IDLE;
00142 
00143   simtime_t answerTime = requestTimeout;
00144   //check if the current rssi value enables us to answer the request
00145   if(isIdleRSSI(it->getValue()) == untilIdle) {
00146     answerTime = now;
00147   }
00148   else {
00149     //iterate through request interval to check when the rssi level
00150     //changes such that the request can be answered
00151     while(it->hasNext() && it->getNextPosition().getTime() < requestTimeout) {
00152       it->next();
00153 
00154       if(isIdleRSSI(it->getValue()) == untilIdle) {
00155         answerTime = it->getPosition().getTime();
00156         break;
00157       }
00158     }
00159   }
00160 
00161   delete it;
00162   delete rssiMapping;
00163 
00164   return answerTime;
00165 }
00166 
00167 simtime_t SNRThresholdDecider::processSignalEnd(AirFrame* frame)
00168 {
00169   assert(frame == currentSignal.first);
00170   // here the Signal is finally processed
00171 
00172   // first collect all necessary information
00173   Mapping* snrMap = calculateSnrMapping(frame);
00174   assert(snrMap);
00175 
00176   const Signal& signal = frame->getSignal();
00177   simtime_t start = signal.getSignalStart();
00178   simtime_t end = start + signal.getSignalLength();
00179 
00180   // NOTE: Since this decider does not consider the amount of time when the signal's SNR is
00181   // below the threshold even the smallest (normally insignificant) drop causes this decider
00182   // to reject reception of the signal.
00183   // Since the default MiXiM-signal is still zero at its exact start and end, these points
00184   // are ignored in the interval passed to the following method.
00185   bool aboveThreshold = checkIfAboveThreshold(snrMap,
00186                         MappingUtils::post(start),
00187                         MappingUtils::pre(end));
00188 
00189   // check if the snrMapping is above the Decider's specific threshold,
00190   // i.e. the Decider has received it correctly
00191   if (aboveThreshold)
00192   {
00193     deciderEV << "SNR is above threshold("<<snrThreshold<<") -> sending up." << endl;
00194     // go on with processing this AirFrame, send it to the Mac-Layer
00195     phy->sendUp(frame, new DeciderResult(true));
00196   } else
00197   {
00198     deciderEV << "SNR is below threshold("<<snrThreshold<<") -> dropped." << endl;
00199   }
00200 
00201   delete snrMap;
00202   snrMap = 0;
00203 
00204 
00205   // we have processed this AirFrame and we prepare to receive the next one
00206   currentSignal.first = 0;
00207 
00208   return notAgain;
00209 }
00210