PhyUtils.cc

00001 #include "PhyUtils.h"
00002 
00003 using namespace std;
00004 
00005 void RadioStateAnalogueModel::filterSignal(Signal& s)
00006 {
00007   simtime_t start = s.getSignalStart();
00008   simtime_t end = start + s.getSignalLength();
00009 
00010   RSAMMapping* attMapping = new RSAMMapping(this, start, end);
00011   s.addAttenuation(attMapping);
00012 }
00013 
00014 void RadioStateAnalogueModel::cleanUpUntil(simtime_t t)
00015 {
00016   // assert that list is not empty
00017   assert(!radioStateAttenuation.empty());
00018 
00019   /* the list contains at least one element */
00020 
00021   // CASE: t is smaller or equal the timepoint of the first element ==> nothing to do, return
00022   if ( t <= radioStateAttenuation.front().getTime() )
00023   {
00024     return;
00025   }
00026 
00027 
00028   // CASE: t is greater than the timepoint of the last element
00029   // ==> clear complete list except the last element, return
00030   if ( t > radioStateAttenuation.back().getTime() )
00031   {
00032     ListEntry lastEntry = radioStateAttenuation.back();
00033     radioStateAttenuation.clear();
00034     radioStateAttenuation.push_back(lastEntry);
00035     return;
00036   }
00037 
00038   /*
00039    * preconditions from now on:
00040    * 1. list contains at least two elements, since 2. + 3.
00041    * 2. t > first_timepoint
00042    * 3. t <= last_timepoint
00043    */
00044 
00045   // get an iterator and set it to the first timepoint >= t
00046   std::list<ListEntry>::iterator it;
00047   it = lower_bound(radioStateAttenuation.begin(), radioStateAttenuation.end(), t);
00048 
00049 
00050   // CASE: list contains an element with exactly the given key
00051   if ( it->getTime() == t )
00052   {
00053     radioStateAttenuation.erase(radioStateAttenuation.begin(), it);
00054     return;
00055   }
00056 
00057   // CASE: t is "in between two elements"
00058   // ==> set the iterators predecessors time to t, it becomes the first element
00059   it--; // go back one element, possible since this one has not been the first one
00060 
00061   it->setTime(t); // set this elements time to t
00062   radioStateAttenuation.erase(radioStateAttenuation.begin(), it); // and erase all previous elements
00063 
00064 }
00065 
00066 void RadioStateAnalogueModel::writeRecvEntry(simtime_t time, double value)
00067 {
00068   // bugfixed on 08.04.2008
00069   assert( (radioStateAttenuation.empty()) || (time >= radioStateAttenuation.back().getTime()) );
00070 
00071   radioStateAttenuation.push_back(ListEntry(time, value));
00072 
00073   if (!currentlyTracking)
00074   {
00075     cleanUpUntil(time);
00076 
00077     assert(radioStateAttenuation.back().getTime() == time);
00078   }
00079 }
00080 
00081 
00082 
00083 
00084 Radio::Radio(int numRadioStates,
00085        bool recordStats,
00086        int initialState,
00087        double minAtt, double maxAtt,
00088        int currentChannel, int nbChannels):
00089   state(initialState), nextState(initialState),
00090   numRadioStates(numRadioStates),
00091   minAtt(minAtt), maxAtt(maxAtt),
00092   rsam(mapStateToAtt(initialState)),
00093   currentChannel(currentChannel), nbChannels(nbChannels)
00094 {
00095   assert(nbChannels > 0);
00096   assert(currentChannel > -1);
00097   assert(currentChannel < nbChannels);
00098 
00099   radioStates.setName("RadioState");
00100   radioStates.setEnabled(recordStats);
00101   radioStates.record(initialState);
00102   radioChannels.setName("RadioChannel");
00103   radioChannels.setEnabled(recordStats);
00104   radioChannels.record(currentChannel);
00105 
00106   // allocate memory for one dimension
00107   swTimes = new simtime_t* [numRadioStates];
00108 
00109   // go through the first dimension and
00110   for (int i = 0; i < numRadioStates; i++)
00111   {
00112     // allocate memory for the second dimension
00113     swTimes[i] = new simtime_t[numRadioStates];
00114   }
00115 
00116   // initialize all matrix entries to 0.0
00117   for (int i = 0; i < numRadioStates; i++)
00118   {
00119     for (int j = 0; j < numRadioStates; j++)
00120     {
00121       swTimes[i][j] = 0;
00122     }
00123   }
00124 }
00125 
00126 Radio::~Radio()
00127 {
00128   // delete all allocated memory for the switching times matrix
00129   for (int i = 0; i < numRadioStates; i++)
00130   {
00131     delete[] swTimes[i];
00132   }
00133 
00134   delete[] swTimes;
00135   swTimes = 0;
00136 }
00137 
00138 simtime_t Radio::switchTo(int newState, simtime_t now)
00139 {
00140   // state to switch to must be in a valid range, i.e. 0 <= newState < numRadioStates
00141   assert(0 <= newState && newState < numRadioStates);
00142 
00143   // state to switch to must not be SWITCHING
00144   assert(newState != SWITCHING);
00145 
00146 
00147   // return error value if newState is the same as the current state
00148   // if (newState == state) return -1;
00149 
00150   // return error value if Radio is currently switching
00151   if (state == SWITCHING) return -1;
00152 
00153 
00154   /* REGULAR CASE */
00155 
00156 
00157   // set the nextState to the newState and the current state to SWITCHING
00158   nextState = newState;
00159   int lastState = state;
00160   state = SWITCHING;
00161   radioStates.record(state);
00162 
00163   // make entry to RSAM
00164   makeRSAMEntry(now, state);
00165 
00166   // return matching entry from the switch times matrix
00167   return swTimes[lastState][nextState];
00168 }
00169 
00170 void Radio::setSwitchTime(int from, int to, simtime_t time)
00171 {
00172   // assert parameters are in valid range
00173   assert(time >= 0.0);
00174   assert(0 <= from && from < numRadioStates);
00175   assert(0 <= to && to < numRadioStates);
00176 
00177   // it shall not be possible to set times to/from SWITCHING
00178   assert(from != SWITCHING && to != SWITCHING);
00179 
00180 
00181   swTimes[from][to] = time;
00182   return;
00183 }
00184 
00185 void Radio::endSwitch(simtime_t now)
00186 {
00187   // make sure we are currently switching
00188   assert(state == SWITCHING);
00189 
00190   // set the current state finally to the next state
00191   state = nextState;
00192   radioStates.record(state);
00193 
00194   // make entry to RSAM
00195   makeRSAMEntry(now, state);
00196 
00197   return;
00198 }
00199 
00200 
00201 
00202 
00203 RSAMConstMappingIterator::RSAMConstMappingIterator
00204               (const RadioStateAnalogueModel* rsam,
00205                simtime_t signalStart,
00206                simtime_t signalEnd) :
00207   rsam(rsam),
00208   signalStart(signalStart),
00209   signalEnd(signalEnd)
00210 {
00211   assert(rsam);
00212 
00213   assert( !(signalStart < rsam->radioStateAttenuation.front().getTime()) );
00214 
00215   jumpToBegin();
00216 }
00217 
00218 void RSAMConstMappingIterator::jumpTo(const Argument& pos)
00219 {
00220   // extract the time-component from the argument
00221   simtime_t t = pos.getTime();
00222 
00223   assert( !(rsam->radioStateAttenuation.empty()) &&
00224       !(t < rsam->radioStateAttenuation.front().getTime()) );
00225 
00226   // current position is already correct
00227   if( t == position.getTime() )
00228     return;
00229 
00230   // this automatically goes over all zero time switches
00231   it = upper_bound(rsam->radioStateAttenuation.begin(), rsam->radioStateAttenuation.end(), t);
00232 
00233   --it;
00234   position.setTime(t);
00235   setNextPosition();
00236 }
00237 
00238 void RSAMConstMappingIterator::setNextPosition()
00239 {
00240   if (hasNext()) // iterator it does not stand on last entry and next entry is before signal end
00241   {
00242     if(position.getTime() < signalStart) //signal start is our first key entry
00243     {
00244       nextPosition.setTime(signalStart);
00245     } else
00246     {
00247       CurrList::const_iterator it2 = it;
00248       it2++;
00249 
00250       assert(it->getTime() <= position.getTime() && position.getTime() < it2->getTime());
00251 
00252       //point in time for the "pre step" of the next real key entry
00253       simtime_t preTime = MappingUtils::pre(it2->getTime());
00254 
00255       if(position.getTime() == preTime) {
00256         nextPosition.setTime(it2->getTime());
00257       }
00258       else {
00259         nextPosition.setTime(preTime);
00260       }
00261     }
00262 
00263   } else // iterator it stands on last entry or next entry whould be behind signal end
00264   {
00265     nextPosition.setTime(position.getTime() + 1);
00266   }
00267 
00268 }
00269 
00270 void RSAMConstMappingIterator::iterateTo(const Argument& pos)
00271 {
00272   // extract the time component from the passed Argument
00273   simtime_t t = pos.getTime();
00274 
00275   // ERROR CASE: iterating to a position before (time) the beginning of the mapping is forbidden
00276   assert( !(rsam->radioStateAttenuation.empty()) &&
00277       !(t < rsam->radioStateAttenuation.front().getTime()) );
00278 
00279   assert( !(t < position.getTime()) );
00280 
00281   // REGULAR CASES:
00282   // t >= position.getTime();
00283 
00284   // we are already exactly there
00285   if( t == position.getTime() )
00286     return;
00287 
00288   // we iterate there going over all zero time switches
00289   iterateToOverZeroSwitches(t);
00290 
00291   // update current position
00292   position.setTime(t);
00293   setNextPosition();
00294 
00295 }
00296 
00297 bool RSAMConstMappingIterator::inRange() const
00298 {
00299   simtime_t t = position.getTime();
00300   simtime_t lastEntryTime = std::max(rsam->radioStateAttenuation.back().getTime(), signalStart);
00301 
00302   return  signalStart <= t
00303       && t <= signalEnd
00304       && t <= lastEntryTime;
00305 
00306 }
00307 
00308 bool RSAMConstMappingIterator::hasNext() const
00309 {
00310   assert( !(rsam->radioStateAttenuation.empty()) );
00311 
00312   CurrList::const_iterator it2 = it;
00313   if (it2 != rsam->radioStateAttenuation.end())
00314   {
00315     it2++;
00316   }
00317 
00318   return  position.getTime() < signalStart
00319       || (it2 != rsam->radioStateAttenuation.end() && it2->getTime() <= signalEnd);
00320 }
00321 
00322 void RSAMConstMappingIterator::iterateToOverZeroSwitches(simtime_t t)
00323 {
00324   if( it != rsam->radioStateAttenuation.end() && !(t < it->getTime()) )
00325   {
00326     // and go over (ignore) all zero-time-switches, to the next greater entry (time)
00327     while( it != rsam->radioStateAttenuation.end() && !(t < it->getTime()) )
00328       it++;
00329 
00330     // go back one step, here the iterator 'it' is placed right
00331     it--;
00332   }
00333 }
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 double RSAMMapping::getValue(const Argument& pos) const
00343 {
00344   // extract the time-component from the argument
00345   simtime_t t = pos.getTime();
00346 
00347   // assert that t is not before the first timepoint in the RSAM
00348   // and receiving list is not empty
00349   assert( !(rsam->radioStateAttenuation.empty()) &&
00350       !(t < rsam->radioStateAttenuation.front().getTime()) );
00351 
00352   /* receiving list contains at least one entry */
00353 
00354   // set an iterator to the first entry with timepoint > t
00355   std::list<RadioStateAnalogueModel::ListEntry>::const_iterator it;
00356   it = upper_bound(rsam->radioStateAttenuation.begin(), rsam->radioStateAttenuation.end(), t);
00357 
00358   // REGULAR CASE: it points to an element that has a predecessor
00359   it--; // go back one entry, this one is significant!
00360 
00361   return it->getValue();
00362 }
00363 
00364 ConstMappingIterator* RSAMMapping::createConstIterator(const Argument& pos)
00365 {
00366   RSAMConstMappingIterator* rsamCMI
00367     = new RSAMConstMappingIterator(rsam, signalStart, signalEnd);
00368 
00369   rsamCMI->jumpTo(pos);
00370 
00371   return rsamCMI;
00372 }