split interference calculation from YansWifiPhy. Move them to InterferenceHelper
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 14 Jun 2008 10:52:10 -0700
changeset 3905 99c9346b5d71
parent 3904 1271239aaec5
child 3906 01acc159ffb1
split interference calculation from YansWifiPhy. Move them to InterferenceHelper
src/devices/wifi/dcf-manager.cc
src/devices/wifi/dcf-manager.h
src/devices/wifi/error-rate-model.cc
src/devices/wifi/error-rate-model.h
src/devices/wifi/interference-helper.cc
src/devices/wifi/interference-helper.h
src/devices/wifi/wifi-phy-state-helper.cc
src/devices/wifi/wifi-phy-state-helper.h
src/devices/wifi/wifi-phy.h
src/devices/wifi/wscript
src/devices/wifi/yans-wifi-phy.cc
src/devices/wifi/yans-wifi-phy.h
--- a/src/devices/wifi/dcf-manager.cc	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/dcf-manager.cc	Sat Jun 14 10:52:10 2008 -0700
@@ -180,8 +180,8 @@
   virtual void NotifyTxStart (Time duration) {
     m_dcf->NotifyTxStartNow (duration);
   }
-  virtual void NotifyCcaBusyStart (Time duration) {
-    m_dcf->NotifyCcaBusyStartNow (duration);
+  virtual void NotifyMaybeCcaBusyStart (Time duration) {
+    m_dcf->NotifyMaybeCcaBusyStartNow (duration);
   }
 private:
   ns3::DcfManager *m_dcf;
@@ -528,7 +528,7 @@
   m_lastTxDuration = duration;
 }
 void 
-DcfManager::NotifyCcaBusyStartNow (Time duration)
+DcfManager::NotifyMaybeCcaBusyStartNow (Time duration)
 {
   MY_DEBUG ("busy start for "<<duration);
   UpdateBackoff ();
--- a/src/devices/wifi/dcf-manager.h	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/dcf-manager.h	Sat Jun 14 10:52:10 2008 -0700
@@ -220,7 +220,7 @@
    *
    * Notify the DCF that a CCA busy period has just started.
    */
-  void NotifyCcaBusyStartNow (Time duration);
+  void NotifyMaybeCcaBusyStartNow (Time duration);
   /**
    * \param duration the value of the received NAV.
    *
--- a/src/devices/wifi/error-rate-model.cc	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/error-rate-model.cc	Sat Jun 14 10:52:10 2008 -0700
@@ -25,6 +25,8 @@
 
 namespace ns3 {
 
+NS_OBJECT_ENSURE_REGISTERED (ErrorRateModel);
+
 TypeId 
 ErrorRateModel::GetTypeId (void)
 {
@@ -38,6 +40,30 @@
 ErrorRateModel::ErrorRateModel ()
 {}
 
+double 
+ErrorRateModel::CalculateSnr (WifiMode txMode, double ber) const
+{
+  // This is a very simple binary search.
+  double low, high, precision;
+  low = 1e-25;
+  high = 1e25;
+  precision = 1e-12;
+  while (high - low > precision) 
+    {
+      NS_ASSERT (high >= low);
+      double middle = low + (high - low) / 2;
+      if ((1 - GetChunkSuccessRate (txMode, middle, 1)) > ber) 
+        {
+          low = middle;
+        } 
+      else 
+        {
+          high = middle;
+        }
+    }
+  return low;
+}
+
 
 double 
 ErrorRateModel::Log2 (double val) const
--- a/src/devices/wifi/error-rate-model.h	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/error-rate-model.h	Sat Jun 14 10:52:10 2008 -0700
@@ -33,6 +33,14 @@
 
   ErrorRateModel ();
 
+  /**
+   * \param txMode a specific transmission mode
+   * \param ber a target ber
+   * \returns the snr which corresponds to the requested
+   *          ber.
+   */
+  double CalculateSnr (WifiMode txMode, double ber) const;
+
   double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const;
 
 private:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/interference-helper.cc	Sat Jun 14 10:52:10 2008 -0700
@@ -0,0 +1,441 @@
+#include "interference-helper.h"
+#include "wifi-phy.h"
+#include "error-rate-model.h"
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("InterferenceHelper");
+
+namespace ns3 {
+
+/****************************************************************
+ *       Phy event class
+ ****************************************************************/
+
+InterferenceHelper::Event::Event (uint32_t size, WifiMode payloadMode, 
+					       enum WifiPreamble preamble,
+					       Time duration, double rxPower)
+  : m_size (size),
+    m_payloadMode (payloadMode),
+    m_preamble (preamble),
+    m_startTime (Simulator::Now ()),
+    m_endTime (m_startTime + duration),
+    m_rxPowerW (rxPower)
+{}
+InterferenceHelper::Event::~Event ()
+{}
+  
+Time 
+InterferenceHelper::Event::GetDuration (void) const 
+{
+  return m_endTime - m_startTime;
+}
+Time 
+InterferenceHelper::Event::GetStartTime (void) const
+{
+  return m_startTime;
+}
+Time 
+InterferenceHelper::Event::GetEndTime (void) const
+{
+  return m_endTime;
+}
+bool 
+InterferenceHelper::Event::Overlaps (Time time) const
+{
+  if (m_startTime <= time &&
+      m_endTime >= time) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+double 
+InterferenceHelper::Event::GetRxPowerW (void) const
+{
+  return m_rxPowerW;
+}
+uint32_t 
+InterferenceHelper::Event::GetSize (void) const
+{
+  return m_size;
+}
+WifiMode 
+InterferenceHelper::Event::GetPayloadMode (void) const
+{
+  return m_payloadMode;
+}
+enum WifiPreamble 
+InterferenceHelper::Event::GetPreambleType (void) const
+{
+  return m_preamble;
+}
+
+/****************************************************************
+ *       Class which records SNIR change events for a 
+ *       short period of time.
+ ****************************************************************/
+
+InterferenceHelper::NiChange::NiChange (Time time, double delta)
+  : m_time (time), m_delta (delta) 
+{}
+Time
+InterferenceHelper::NiChange::GetTime (void) const
+{
+  return m_time;
+}
+double 
+InterferenceHelper::NiChange::GetDelta (void) const
+{
+  return m_delta;
+}
+bool 
+InterferenceHelper::NiChange::operator < (InterferenceHelper::NiChange const &o) const
+{
+  return (m_time < o.m_time)?true:false;
+}
+
+/****************************************************************
+ *       The actual InterferenceHelper
+ ****************************************************************/
+
+InterferenceHelper::InterferenceHelper ()
+  : m_80211a (false)
+{
+  m_errorRateModel = Create<ErrorRateModel> ();
+}
+
+Ptr<InterferenceHelper::Event> 
+InterferenceHelper::Add (uint32_t size, WifiMode payloadMode, 
+			 enum WifiPreamble preamble,
+			 Time duration, double rxPowerW)
+{
+  Ptr<InterferenceHelper::Event> event;
+
+  event = Create<InterferenceHelper::Event> 
+    (size,
+     payloadMode,
+     preamble,
+     duration,
+     rxPowerW);
+
+  AppendEvent (event);
+  return event;
+}
+
+Time 
+InterferenceHelper::GetMaxPacketDuration (void) const
+{
+  return m_maxPacketDuration;
+}
+
+void 
+InterferenceHelper::SetNoiseFloorW (double noiseFloor)
+{
+  m_noiseFloorW = noiseFloor;
+}
+
+double 
+InterferenceHelper::GetNoiseFloorW (void) const
+{
+  return m_noiseFloorW;
+}
+
+void 
+InterferenceHelper::SetErrorRateModel (Ptr<ErrorRateModel> rate)
+{
+  m_errorRateModel = rate;
+}
+
+Ptr<ErrorRateModel> 
+InterferenceHelper::GetErrorRateModel (void) const
+{
+  return m_errorRateModel;
+}
+
+Time 
+InterferenceHelper::GetEnergyDuration (double energyW)
+{
+  Time now = Simulator::Now ();
+
+  // first, we iterate over all events and, each event
+  // which contributes energy to the channel now is 
+  // appended to the noise interference array.
+  Events::const_iterator i = m_events.begin ();
+  double noiseInterferenceW = 0.0;
+  NiChanges ni;
+  while (i != m_events.end ()) 
+    {
+      Ptr<Event> ev = *i;
+      NS_ASSERT (ev->GetStartTime () <= now);
+      if (ev->GetEndTime () > now)
+	{
+          ni.push_back (NiChange (ev->GetEndTime (), -ev->GetRxPowerW ()));
+          noiseInterferenceW += ev->GetRxPowerW ();
+	}
+      i++;
+    }
+  if (noiseInterferenceW < energyW)
+    {
+      return MicroSeconds (0);
+    }
+
+  /* quicksort vector of NI changes by time. 
+   */
+  std::sort (ni.begin (), ni.end (), std::less<NiChange> ());
+
+  // Now, we iterate the piecewise linear noise function
+  Time end = now;
+  for (NiChanges::const_iterator i = ni.begin (); i != ni.end (); i++) 
+    {
+      noiseInterferenceW += i->GetDelta ();
+      end = i->GetTime ();
+      if (noiseInterferenceW < energyW) 
+	{
+	  break;
+	}
+    }
+  return end - now;
+}
+
+Time
+InterferenceHelper::CalculateTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamble preamble) const
+{
+  NS_ASSERT (m_80211a);
+  uint64_t delay = 0;
+  delay += m_plcpLongPreambleDelayUs;
+  // symbol duration is 4us
+  delay += 4;
+  delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 4e-6) * 4);
+  return MicroSeconds (delay);
+}
+
+void
+InterferenceHelper::Configure80211aParameters (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_80211a = true;
+  m_plcpLongPreambleDelayUs = 16;
+  m_plcpShortPreambleDelayUs = 16;
+  m_longPlcpHeaderMode = WifiPhy::g_6mba;
+  m_shortPlcpHeaderMode = WifiPhy::g_6mba;
+  m_plcpHeaderLength = 4 + 1 + 12 + 1 + 6;
+  /* 4095 bytes at a 6Mb/s rate with a 1/2 coding rate. */
+  m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::g_6mba, WIFI_PREAMBLE_LONG);
+}
+
+void 
+InterferenceHelper::AppendEvent (Ptr<InterferenceHelper::Event> event)
+{
+  /* attempt to remove the events which are 
+   * not useful anymore. 
+   * i.e.: all events which end _before_
+   *       now - m_maxPacketDuration
+   */
+  
+  if (Simulator::Now () > GetMaxPacketDuration ())
+    {
+      Time end = Simulator::Now () - GetMaxPacketDuration ();
+      Events::iterator i = m_events.begin ();
+      while (i != m_events.end () &&
+             (*i)->GetEndTime () <= end) 
+        {
+          i++;
+        }
+      m_events.erase (m_events.begin (), i);
+    } 
+  m_events.push_back (event);
+}
+
+
+double
+InterferenceHelper::CalculateSnr (double signal, double noiseInterference, WifiMode mode) const
+{
+  // thermal noise at 290K in J/s = W
+  static const double BOLTZMANN = 1.3803e-23;
+  double Nt = BOLTZMANN * 290.0 * mode.GetBandwidth ();
+  // receiver noise Floor (W)
+  double noiseFloor = m_noiseFloorW * Nt;
+  double noise = noiseFloor + noiseInterference;
+  double snr = signal / noise;
+  return snr;
+}
+
+double
+InterferenceHelper::CalculateNoiseInterferenceW (Ptr<InterferenceHelper::Event> event, NiChanges *ni) const
+{
+  Events::const_iterator i = m_events.begin ();
+  double noiseInterference = 0.0;
+  while (i != m_events.end ()) 
+    {
+      if (event == (*i)) 
+        {
+          i++;
+          continue;
+        }
+      if (event->Overlaps ((*i)->GetStartTime ())) 
+        {
+          ni->push_back (NiChange ((*i)->GetStartTime (), (*i)->GetRxPowerW ()));
+        }
+      if (event->Overlaps ((*i)->GetEndTime ())) 
+        {
+          ni->push_back (NiChange ((*i)->GetEndTime (), -(*i)->GetRxPowerW ()));
+        }
+      if ((*i)->Overlaps (event->GetStartTime ())) 
+        {
+          noiseInterference += (*i)->GetRxPowerW ();
+        }
+      i++;
+    }
+  ni->push_back (NiChange (event->GetStartTime (), noiseInterference));
+  ni->push_back (NiChange (event->GetEndTime (), 0));
+
+  /* quicksort vector of NI changes by time. */
+  std::sort (ni->begin (), ni->end (), std::less<NiChange> ());
+
+  return noiseInterference;
+}
+
+double
+InterferenceHelper::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode) const
+{
+  if (duration == NanoSeconds (0)) {
+    return 1.0;
+  }
+  uint32_t rate = mode.GetPhyRate ();
+  uint64_t nbits = (uint64_t)(rate * duration.GetSeconds ());
+  double csr = m_errorRateModel->GetChunkSuccessRate (mode, snir, (uint32_t)nbits);
+  return csr;
+}
+
+double 
+InterferenceHelper::CalculatePer (Ptr<const InterferenceHelper::Event> event, NiChanges *ni) const
+{  
+  double psr = 1.0; /* Packet Success Rate */
+  NiChanges::iterator j = ni->begin ();
+  Time previous = (*j).GetTime ();
+  uint64_t plcpPreambleDelayUs;
+  WifiMode payloadMode = event->GetPayloadMode ();
+  WifiMode headerMode;
+  switch (event->GetPreambleType ()) {
+  case WIFI_PREAMBLE_LONG:
+    plcpPreambleDelayUs = m_plcpLongPreambleDelayUs;
+    headerMode = m_longPlcpHeaderMode;
+    break;
+  case WIFI_PREAMBLE_SHORT:
+    plcpPreambleDelayUs = m_plcpShortPreambleDelayUs;
+    headerMode = m_shortPlcpHeaderMode;
+    break;
+  default:
+    NS_ASSERT (false);
+    // only to quiet compiler. Really stupid.
+    plcpPreambleDelayUs = 0;
+    headerMode = m_shortPlcpHeaderMode;
+    break;
+  }
+  Time plcpHeaderStart = (*j).GetTime () + MicroSeconds (plcpPreambleDelayUs);
+  Time plcpPayloadStart = plcpHeaderStart + 
+    Seconds ((m_plcpHeaderLength + 0.0) / headerMode.GetDataRate ());
+  double noiseInterferenceW = (*j).GetDelta ();
+  double powerW = event->GetRxPowerW ();
+
+  j++;
+  while (ni->end () != j) 
+    {
+      Time current = (*j).GetTime ();
+      NS_ASSERT (current >= previous);
+    
+      if (previous >= plcpPayloadStart) 
+        {
+          psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
+                                                          noiseInterferenceW, 
+                                                          payloadMode), 
+                                            current - previous,
+                                            payloadMode);
+        } 
+      else if (previous >= plcpHeaderStart) 
+        {
+          if (current >= plcpPayloadStart) 
+            {
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
+                                                              noiseInterferenceW, 
+                                                              headerMode), 
+                                                plcpPayloadStart - previous,
+                                                headerMode);
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
+                                                              noiseInterferenceW, 
+                                                              payloadMode),
+                                                current - plcpPayloadStart,
+                                                payloadMode);
+            } 
+          else 
+            {
+              NS_ASSERT (current >= plcpHeaderStart);
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
+                                                              noiseInterferenceW, 
+                                                              headerMode), 
+                                                current - previous,
+                                                headerMode);
+            }
+        } 
+      else 
+        {
+          if (current >= plcpPayloadStart) 
+            {
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
+                                                              noiseInterferenceW, 
+                                                              headerMode), 
+                                                plcpPayloadStart - plcpHeaderStart,
+                                                headerMode);
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
+                                                              noiseInterferenceW, 
+                                                              payloadMode), 
+                                                current - plcpPayloadStart,
+                                                payloadMode);
+            } 
+          else if (current >= plcpHeaderStart) 
+            {
+              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
+                                                              noiseInterferenceW, 
+                                                              headerMode), 
+                                                current - plcpHeaderStart,
+                                                headerMode);
+            }
+        }
+
+      noiseInterferenceW += (*j).GetDelta ();
+      previous = (*j).GetTime ();
+      j++;
+    }
+
+  double per = 1 - psr;
+  return per;
+}
+
+
+struct InterferenceHelper::SnrPer 
+InterferenceHelper::CalculateSnrPer (Ptr<InterferenceHelper::Event> event)
+{
+  NiChanges ni;
+  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
+  double snr = CalculateSnr (event->GetRxPowerW (),
+                             noiseInterferenceW,
+                             event->GetPayloadMode ());
+  
+  /* calculate the SNIR at the start of the packet and accumulate
+   * all SNIR changes in the snir vector.
+   */
+  double per = CalculatePer (event, &ni);
+
+  struct SnrPer snrPer;
+  snrPer.snr = snr;
+  snrPer.per = per;
+  return snrPer;
+}
+
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/interference-helper.h	Sat Jun 14 10:52:10 2008 -0700
@@ -0,0 +1,107 @@
+#ifndef INTERFERENCE_HELPER_H
+#define INTERFERENCE_HELPER_H
+
+#include <stdint.h>
+#include <vector>
+#include <list>
+#include "wifi-mode.h"
+#include "wifi-preamble.h"
+#include "ns3/nstime.h"
+#include "ns3/ref-count-base.h"
+
+namespace ns3 {
+
+class ErrorRateModel;
+
+class InterferenceHelper
+{
+public:
+  class Event : public RefCountBase
+  {
+  public:
+    Event (uint32_t size, WifiMode payloadMode, 
+	     enum WifiPreamble preamble,
+	     Time duration, double rxPower);
+    virtual ~Event ();
+  
+    Time GetDuration (void) const;
+    Time GetStartTime (void) const;
+    Time GetEndTime (void) const;
+    bool Overlaps (Time time) const;
+    double GetRxPowerW (void) const;
+    uint32_t GetSize (void) const;
+    WifiMode GetPayloadMode (void) const;
+    enum WifiPreamble GetPreambleType (void) const;
+  private:
+    uint32_t m_size;
+    WifiMode m_payloadMode;
+    enum WifiPreamble m_preamble;
+    Time m_startTime;
+    Time m_endTime;
+    double m_rxPowerW;
+  };
+  struct SnrPer 
+  {
+    double snr;
+    double per;
+  };
+
+  InterferenceHelper ();
+
+  void Configure80211aParameters (void);
+  void SetNoiseFloorW (double noiseFloor);
+  void SetErrorRateModel (Ptr<ErrorRateModel> rate);
+
+  double GetNoiseFloorW (void) const;
+  Ptr<ErrorRateModel> GetErrorRateModel (void) const;
+
+
+  /**
+   * \param energyW the minimum energy (W) requested
+   * \returns the expected amount of time the observed 
+   *          energy on the medium will be higher than
+   *          the requested threshold.
+   */
+  Time GetEnergyDuration (double energyW);
+  Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamble preamble) const;
+  Ptr<InterferenceHelper::Event> Add (uint32_t size, WifiMode payloadMode, 
+				      enum WifiPreamble preamble,
+				      Time duration, double rxPower);
+
+  struct InterferenceHelper::SnrPer CalculateSnrPer (Ptr<InterferenceHelper::Event> event);
+private:
+  class NiChange {
+  public:
+    NiChange (Time time, double delta);
+    Time GetTime (void) const;
+    double GetDelta (void) const;
+    bool operator < (NiChange const &o) const;
+  private:
+    Time m_time;
+    double m_delta;
+  };
+  typedef std::vector <NiChange> NiChanges;
+  typedef std::list<Ptr<Event> > Events;
+
+  void AppendEvent (Ptr<Event> event);
+  double CalculateNoiseInterferenceW (Ptr<Event> event, NiChanges *ni) const;
+  double CalculateSnr (double signal, double noiseInterference, WifiMode mode) const;
+  double CalculateChunkSuccessRate (double snir, Time delay, WifiMode mode) const;
+  double CalculatePer (Ptr<const Event> event, NiChanges *ni) const;
+  Time GetMaxPacketDuration (void) const;
+
+  uint64_t m_plcpLongPreambleDelayUs;
+  uint64_t m_plcpShortPreambleDelayUs;
+  WifiMode m_longPlcpHeaderMode;
+  WifiMode m_shortPlcpHeaderMode;
+  uint32_t m_plcpHeaderLength;
+  Time m_maxPacketDuration;
+  double m_noiseFloorW;
+  Events m_events;
+  bool m_80211a;
+  Ptr<ErrorRateModel> m_errorRateModel;
+};
+
+} // namespace ns3
+
+#endif /* INTERFERENCE_HELPER_H */
--- a/src/devices/wifi/wifi-phy-state-helper.cc	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/wifi-phy-state-helper.cc	Sat Jun 14 10:52:10 2008 -0700
@@ -26,6 +26,8 @@
 
 namespace ns3 {
 
+NS_OBJECT_ENSURE_REGISTERED (WifiPhyStateHelper);
+
 TypeId 
 WifiPhyStateHelper::GetTypeId (void)
 {
@@ -220,10 +222,10 @@
   }
 }
 void 
-WifiPhyStateHelper::NotifyCcaBusyStart (Time duration)
+WifiPhyStateHelper::NotifyMaybeCcaBusyStart (Time duration)
 {
   for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
-    (*i)->NotifyCcaBusyStart (duration);
+    (*i)->NotifyMaybeCcaBusyStart (duration);
   }
 }
 
@@ -343,7 +345,7 @@
 void
 WifiPhyStateHelper::SwitchMaybeToCcaBusy (Time duration)
 {
-  NotifyCcaBusyStart (duration);
+  NotifyMaybeCcaBusyStart (duration);
   Time now = Simulator::Now ();
   switch (GetState ()) {
   case WifiPhy::IDLE:
@@ -357,7 +359,7 @@
     break;
   }
   m_startCcaBusy = now;
-  m_endCcaBusy = Max (m_endCcaBusy, now + duration);
+  m_endCcaBusy = std::max (m_endCcaBusy, now + duration);
 }
 
 } // namespace ns3
--- a/src/devices/wifi/wifi-phy-state-helper.h	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/wifi-phy-state-helper.h	Sat Jun 14 10:52:10 2008 -0700
@@ -65,7 +65,7 @@
   void NotifySyncStart (Time duration);
   void NotifySyncEndOk (void);
   void NotifySyncEndError (void);
-  void NotifyCcaBusyStart (Time duration);
+  void NotifyMaybeCcaBusyStart (Time duration);
   void DoSwitchFromSync (void);
 
   bool m_syncing;
--- a/src/devices/wifi/wifi-phy.h	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/wifi-phy.h	Sat Jun 14 10:52:10 2008 -0700
@@ -46,22 +46,24 @@
   /**
    * \param duration the expected duration of the packet reception.
    *
-   * we have received the first bit of a packet. We decided
+   * We have received the first bit of a packet. We decided
    * that we could synchronize on this packet. It does not mean
    * we will be able to successfully receive completely the
-   * whole packet. It means we will report a BUSY status.
-   * NotifyRxEndOk or NotifyRxEndError will be invoked later 
-   * to report whether or not the packet was successfully received.
+   * whole packet. It means that we will report a BUSY status until
+   * one of the following happens:
+   *   - NotifyRxEndOk
+   *   - NotifyExEndError
+   *   - NotifyTxStart
    */
   virtual void NotifyRxStart (Time duration) = 0;
   /**
-   * we have received the last bit of a packet for which
+   * We have received the last bit of a packet for which
    * NotifyRxStart was invoked first and, the packet has
    * been successfully received.
    */
   virtual void NotifyRxEndOk (void) = 0;  
   /**
-   * we have received the last bit of a packet for which
+   * We have received the last bit of a packet for which
    * NotifyRxStart was invoked first and, the packet has
    * _not_ been successfully received.
    */
@@ -70,14 +72,28 @@
    * \param duration the expected transmission duration.
    *
    * We are about to send the first bit of the packet.
+   * We do not send any event to notify the end of 
+   * transmission. Listeners should assume that the
+   * channel implicitely reverts to the idle state
+   * unless they have received a cca busy report.
    */
   virtual void NotifyTxStart (Time duration) = 0;
   /**
    * \param duration the expected busy duration.
    *
-   * We are going to be cca-busy for a while.
+   * This method does not really report a real state
+   * change as opposed to the other methods in this class.
+   * It merely reports that, unless the medium is reported
+   * busy through NotifyTxStart or NotifyRxStart/End, 
+   * it will be busy as defined by the currently selected 
+   * CCA mode.
+   *
+   * Typical client code which wants to have a clear picture
+   * of the CCA state will need to keep track of the time at
+   * which the last NotifyCcaBusyStart method is called and
+   * what duration it reported.
    */
-  virtual void NotifyCcaBusyStart (Time duration) = 0;
+  virtual void NotifyMaybeCcaBusyStart (Time duration) = 0;
 };
 
 
--- a/src/devices/wifi/wscript	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/wscript	Sat Jun 14 10:52:10 2008 -0700
@@ -13,6 +13,7 @@
         'wifi-phy.cc',
         'wifi-phy-state-helper.cc',
         'error-rate-model.cc',
+        'interference-helper.cc',
         'yans-wifi-phy.cc',
         'yans-wifi-channel.cc',
         'wifi-mac-header.cc',
@@ -60,6 +61,7 @@
         'yans-wifi-phy.h',
         'yans-wifi-channel.h',
         'wifi-phy.h',
+        'interference-helper.h',
         'wifi-remote-station-manager.h',
         'arf-wifi-manager.h',
         'aarf-wifi-manager.h',
--- a/src/devices/wifi/yans-wifi-phy.cc	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/yans-wifi-phy.cc	Sat Jun 14 10:52:10 2008 -0700
@@ -39,109 +39,6 @@
 
 namespace ns3 {
 
-/****************************************************************
- *       Phy event class
- ****************************************************************/
-
-class RxEvent
-{
-public:
-  RxEvent (uint32_t size, WifiMode payloadMode, 
-           enum WifiPreamble preamble,
-           Time duration, double rxPower)
-    : m_size (size),
-      m_payloadMode (payloadMode),
-      m_preamble (preamble),
-      m_startTime (Simulator::Now ()),
-      m_endTime (m_startTime + duration),
-      m_rxPowerW (rxPower),
-      m_refCount (1)
-  {}
-  ~RxEvent ()
-  {
-    NS_ASSERT (m_refCount == 0);
-  }
-  
-  void Ref (void) const {
-    m_refCount++;
-  }
-  void Unref (void) const {
-    m_refCount--;
-    if (m_refCount == 0) {
-      delete this;
-    }
-  }
-  Time GetDuration (void) const {
-    return m_endTime - m_startTime;
-  }
-  Time GetStartTime (void) const {
-    return m_startTime;
-  }
-  Time GetEndTime (void) const {
-    return m_endTime;
-  }
-  bool Overlaps (Time time) const {
-    if (m_startTime <= time &&
-        m_endTime >= time) {
-      return true;
-    } else {
-      return false;
-    }
-  }
-  double GetRxPowerW (void) const {
-    return m_rxPowerW;
-  }
-  uint32_t GetSize (void) const {
-    return m_size;
-  }
-  WifiMode GetPayloadMode (void) const {
-    return m_payloadMode;
-  }
-  enum WifiPreamble GetPreambleType (void) const {
-    return m_preamble;
-  }
-
-private:
-  uint32_t m_size;
-  WifiMode m_payloadMode;
-  enum WifiPreamble m_preamble;
-  Time m_startTime;
-  Time m_endTime;
-  double m_rxPowerW;
-  mutable int m_refCount;
-};
-
-
-/****************************************************************
- *       Class which records SNIR change events for a 
- *       short period of time.
- ****************************************************************/
-
-YansWifiPhy::NiChange::NiChange (Time time, double delta)
-  : m_time (time), m_delta (delta) 
-{}
-Time
-YansWifiPhy::NiChange::GetTime (void) const
-{
-  return m_time;
-}
-double 
-YansWifiPhy::NiChange::GetDelta (void) const
-{
-  return m_delta;
-}
-bool 
-YansWifiPhy::NiChange::operator < (YansWifiPhy::NiChange const &o) const
-{
-  return (m_time < o.m_time)?true:false;
-}
-
-
-
-/****************************************************************
- *       The actual YansWifiPhy class
- ****************************************************************/
-
 NS_OBJECT_ENSURE_REGISTERED (YansWifiPhy);
 
 TypeId 
@@ -157,6 +54,13 @@
                    MakeDoubleAccessor (&YansWifiPhy::SetEdThreshold,
                                        &YansWifiPhy::GetEdThreshold),
                    MakeDoubleChecker<double> ())
+    .AddAttribute ("CcaMode1Threshold",
+                   "The energy of a received signal should be higher than "
+                   "this threshold (dbm) to allow the PHY layer to declare CCA BUSY state",
+                   DoubleValue (-140.0),
+                   MakeDoubleAccessor (&YansWifiPhy::SetCcaMode1Threshold,
+                                       &YansWifiPhy::GetCcaMode1Threshold),
+                   MakeDoubleChecker<double> ())
     .AddAttribute ("TxGain",
                    "Transmission gain (dB).",
                    DoubleValue (1.0),
@@ -213,7 +117,6 @@
 {
   NS_LOG_FUNCTION (this);
   m_state = CreateObject<WifiPhyStateHelper> ();
-  m_errorRateModel = Create<ErrorRateModel> ();
 }
 
 YansWifiPhy::~YansWifiPhy ()
@@ -226,7 +129,6 @@
 {
   NS_LOG_FUNCTION (this);
   m_channel = 0;
-  m_events.clear ();
   m_modes.clear ();
 }
 
@@ -253,7 +155,7 @@
 YansWifiPhy::SetRxNoise (double db)
 {
   NS_LOG_FUNCTION (this << db);
-  m_rxNoiseRatio = DbToRatio (db);
+  m_interference.SetNoiseFloorW (DbToRatio (db));
 }
 void 
 YansWifiPhy::SetTxPowerStart (double start)
@@ -291,10 +193,21 @@
   NS_LOG_FUNCTION (this << threshold);
   m_edThresholdW = DbmToW (threshold);
 }
+void 
+YansWifiPhy::SetCcaMode1Threshold (double threshold)
+{
+  NS_LOG_FUNCTION (this << threshold);
+  m_ccaMode1ThresholdW = DbmToW (threshold);
+}
+void 
+YansWifiPhy::SetErrorRateModel (Ptr<ErrorRateModel> rate)
+{
+  m_interference.SetErrorRateModel (rate);
+}
 double 
 YansWifiPhy::GetRxNoise (void) const
 {
-  return RatioToDb (m_rxNoiseRatio);
+  return RatioToDb (m_interference.GetNoiseFloorW ());
 }
 double 
 YansWifiPhy::GetTxPowerStart (void) const
@@ -323,6 +236,24 @@
   return WToDbm (m_edThresholdW);
 }
 
+double 
+YansWifiPhy::GetCcaMode1Threshold (void) const
+{
+  return WToDbm (m_ccaMode1ThresholdW);
+}
+
+Ptr<ErrorRateModel> 
+YansWifiPhy::GetErrorRateModel (void) const
+{
+  return m_interference.GetErrorRateModel ();
+}
+
+double 
+YansWifiPhy::CalculateSnr (WifiMode txMode, double ber) const
+{
+  return m_interference.GetErrorRateModel ()->CalculateSnr (txMode, ber);
+}
+
 Ptr<WifiChannel> 
 YansWifiPhy::GetChannel (void) const
 {
@@ -347,9 +278,9 @@
 }
 void 
 YansWifiPhy::StartReceivePacket (Ptr<Packet> packet, 
-                             double rxPowerDbm,
-                             WifiMode txMode,
-                             enum WifiPreamble preamble)
+                                 double rxPowerDbm,
+                                 WifiMode txMode,
+                                 enum WifiPreamble preamble)
 {
   NS_LOG_FUNCTION (this << packet << rxPowerDbm << txMode << preamble);
   rxPowerDbm += m_rxGainDb;
@@ -357,12 +288,12 @@
   Time rxDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
   Time endRx = Simulator::Now () + rxDuration;
 
-  Ptr<RxEvent> event = Create<RxEvent> (packet->GetSize (), 
-                                        txMode,
-                                        preamble,
-                                        rxDuration,
-                                        rxPowerW);
-  AppendEvent (event);
+  Ptr<InterferenceHelper::Event> event;
+  event = m_interference.Add (packet->GetSize (), 
+                              txMode,
+                              preamble,
+                              rxDuration,
+                              rxPowerW);
 
   switch (m_state->GetState ()) {
   case YansWifiPhy::SYNC:
@@ -409,34 +340,16 @@
   return;
 
  maybeCcaBusy:
+  // We are here because we have received the first bit of a packet and we are
+  // not going to be able to synchronize on it
+  // In this model, CCA becomes busy when the aggregation of all signals as
+  // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
 
-  if (rxPowerW > m_edThresholdW) 
-    {
-      m_state->SwitchMaybeToCcaBusy (rxDuration);
-    } 
-  else 
+  Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaMode1ThresholdW);
+  if (!delayUntilCcaEnd.IsZero ())
     {
-      double threshold = m_edThresholdW - rxPowerW;
-      NiChanges ni;
-      CalculateNoiseInterferenceW (event, &ni);
-      double noiseInterferenceW = 0.0;
-      Time end = Simulator::Now ();
-      for (NiChanges::const_iterator i = ni.begin (); i != ni.end (); i++) 
-        {
-          noiseInterferenceW += i->GetDelta ();
-          if (noiseInterferenceW < threshold) 
-            {
-              break;
-            }
-          end = i->GetTime ();
-        }
-      if (end > Simulator::Now ()) 
-        {
-          Time delta = end - Simulator::Now ();
-          m_state->SwitchMaybeToCcaBusy (delta);
-        }
+      m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
     }
-
 }
 void 
 YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower)
@@ -475,64 +388,11 @@
   return m_nTxPower;
 }
 
-double 
-YansWifiPhy::CalculateSnr (WifiMode txMode, double ber) const
-{
-  double low, high, precision;
-  low = 1e-25;
-  high = 1e25;
-  precision = 1e-12;
-  while (high - low > precision) 
-    {
-      NS_ASSERT (high >= low);
-      double middle = low + (high - low) / 2;
-      if ((1 - m_errorRateModel->GetChunkSuccessRate (txMode, middle, 1)) > ber) 
-        {
-          low = middle;
-        } 
-      else 
-        {
-          high = middle;
-        }
-    }
-  return low;
-}
-
-void
-YansWifiPhy::Configure80211aParameters (void)
-{
-  NS_LOG_FUNCTION (this);
-  m_plcpLongPreambleDelayUs = 16;
-  m_plcpShortPreambleDelayUs = 16;
-  m_longPlcpHeaderMode = g_6mba;
-  m_shortPlcpHeaderMode = g_6mba;
-  m_plcpHeaderLength = 4 + 1 + 12 + 1 + 6;
-  /* 4095 bytes at a 6Mb/s rate with a 1/2 coding rate. */
-  m_maxPacketDuration = CalculateTxDuration (4095, g_6mba, WIFI_PREAMBLE_LONG);
-}
-
-void
-YansWifiPhy::PrintModes (void) const
-{
-#if 0
-  for (double db = -10; db < 30; db+= 0.5) {
-    double snr = DbToRatio (db);
-    std::cout <<snr<<" ";
-    for (uint8_t i = 0; i < GetNModes (); i++) {
-      WifiMode mode = GetMode (i);
-      double ber = 1-m_errorRateModel->GetChunkSuccessRate (mode,snr, 2000*8);
-      std::cout <<ber<< " ";
-    }
-    std::cout << std::endl;
-  }
-#endif
-}
-
 void
 YansWifiPhy::Configure80211a (void)
 {
   NS_LOG_FUNCTION (this);
-  Configure80211aParameters ();
+  m_interference.Configure80211aParameters ();
   m_modes.push_back (g_6mba);
   m_modes.push_back (g_9mba);
   m_modes.push_back (g_12mba);
@@ -541,22 +401,18 @@
   m_modes.push_back (g_36mba);
   m_modes.push_back (g_48mba);
   m_modes.push_back (g_54mba);
-
-  PrintModes ();
 }
 
 void
 YansWifiPhy::ConfigureHolland (void)
 {
   NS_LOG_FUNCTION (this);
-  Configure80211aParameters ();
+  m_interference.Configure80211aParameters ();
   m_modes.push_back (g_6mba);
   m_modes.push_back (g_12mba);
   m_modes.push_back (g_18mba);
   m_modes.push_back (g_36mba);
   m_modes.push_back (g_54mba);
-
-  PrintModes ();
 }
 
 void 
@@ -609,28 +465,12 @@
   return m_state->GetLastRxStartTime ();
 }
 
-
-Time
-YansWifiPhy::CalculateTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamble preamble) const
+Time 
+YansWifiPhy::CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const
 {
-  uint64_t delay = 0;
-  switch (m_standard) {
-  case WIFI_PHY_STANDARD_80211a:
-  case WIFI_PHY_STANDARD_holland: {
-    delay += m_plcpLongPreambleDelayUs;
-    // symbol duration is 4us
-    delay += 4;
-    delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 4e-6) * 4);
-  } break;
-  default:
-    // quiet compiler.
-    NS_ASSERT (false);
-    break;
-  }
-  return MicroSeconds (delay);
+  return m_interference.CalculateTxDuration (size, payloadMode, preamble);
 }
 
-
 double 
 YansWifiPhy::DbToRatio (double dB) const
 {
@@ -663,12 +503,6 @@
   return m_edThresholdW;
 }
 
-Time
-YansWifiPhy::GetMaxPacketDuration (void) const
-{
-  return m_maxPacketDuration;
-}
-
 double 
 YansWifiPhy::GetPowerDbm (uint8_t power) const
 {
@@ -678,225 +512,27 @@
   return dbm;
 }
 
-
-void 
-YansWifiPhy::AppendEvent (Ptr<RxEvent> event)
-{
-  /* attempt to remove the events which are 
-   * not useful anymore. 
-   * i.e.: all events which end _before_
-   *       now - m_maxPacketDuration
-   */
-  
-  if (Simulator::Now () > GetMaxPacketDuration ())
-    {
-      Time end = Simulator::Now () - GetMaxPacketDuration ();
-      Events::iterator i = m_events.begin ();
-      while (i != m_events.end () &&
-             (*i)->GetEndTime () <= end) 
-        {
-          i++;
-        }
-      m_events.erase (m_events.begin (), i);
-    } 
-  m_events.push_back (event);
-}
-
-
-double
-YansWifiPhy::CalculateSnr (double signal, double noiseInterference, WifiMode mode) const
-{
-  // thermal noise at 290K in J/s = W
-  static const double BOLTZMANN = 1.3803e-23;
-  double Nt = BOLTZMANN * 290.0 * mode.GetBandwidth ();
-  // receiver noise Floor (W)
-  double noiseFloor = m_rxNoiseRatio * Nt;
-  double noise = noiseFloor + noiseInterference;
-  double snr = signal / noise;
-  return snr;
-}
-
-double
-YansWifiPhy::CalculateNoiseInterferenceW (Ptr<RxEvent> event, NiChanges *ni) const
-{
-  Events::const_iterator i = m_events.begin ();
-  double noiseInterference = 0.0;
-  while (i != m_events.end ()) 
-    {
-      if (event == (*i)) 
-        {
-          i++;
-          continue;
-        }
-      if (event->Overlaps ((*i)->GetStartTime ())) 
-        {
-          ni->push_back (NiChange ((*i)->GetStartTime (), (*i)->GetRxPowerW ()));
-        }
-      if (event->Overlaps ((*i)->GetEndTime ())) 
-        {
-          ni->push_back (NiChange ((*i)->GetEndTime (), -(*i)->GetRxPowerW ()));
-        }
-      if ((*i)->Overlaps (event->GetStartTime ())) 
-        {
-          noiseInterference += (*i)->GetRxPowerW ();
-        }
-      i++;
-    }
-  ni->push_back (NiChange (event->GetStartTime (), noiseInterference));
-  ni->push_back (NiChange (event->GetEndTime (), 0));
-
-  /* quicksort vector of NI changes by time. */
-  std::sort (ni->begin (), ni->end (), std::less<NiChange> ());
-
-  return noiseInterference;
-}
-
-double
-YansWifiPhy::CalculateChunkSuccessRate (double snir, Time duration, WifiMode mode) const
-{
-  if (duration == NanoSeconds (0)) {
-    return 1.0;
-  }
-  uint32_t rate = mode.GetPhyRate ();
-  uint64_t nbits = (uint64_t)(rate * duration.GetSeconds ());
-  double csr = m_errorRateModel->GetChunkSuccessRate (mode, snir, (uint32_t)nbits);
-  return csr;
-}
-
-double 
-YansWifiPhy::CalculatePer (Ptr<const RxEvent> event, NiChanges *ni) const
-{  
-  double psr = 1.0; /* Packet Success Rate */
-  NiChanges::iterator j = ni->begin ();
-  Time previous = (*j).GetTime ();
-  uint64_t plcpPreambleDelayUs;
-  WifiMode payloadMode = event->GetPayloadMode ();
-  WifiMode headerMode;
-  switch (event->GetPreambleType ()) {
-  case WIFI_PREAMBLE_LONG:
-    plcpPreambleDelayUs = m_plcpLongPreambleDelayUs;
-    headerMode = m_longPlcpHeaderMode;
-    break;
-  case WIFI_PREAMBLE_SHORT:
-    plcpPreambleDelayUs = m_plcpShortPreambleDelayUs;
-    headerMode = m_shortPlcpHeaderMode;
-    break;
-  default:
-    NS_ASSERT (false);
-    // only to quiet compiler. Really stupid.
-    plcpPreambleDelayUs = 0;
-    headerMode = m_shortPlcpHeaderMode;
-    break;
-  }
-  Time plcpHeaderStart = (*j).GetTime () + MicroSeconds (plcpPreambleDelayUs);
-  Time plcpPayloadStart = plcpHeaderStart + 
-    Seconds ((m_plcpHeaderLength + 0.0) / headerMode.GetDataRate ());
-  double noiseInterferenceW = (*j).GetDelta ();
-  double powerW = event->GetRxPowerW ();
-
-  j++;
-  while (ni->end () != j) 
-    {
-      Time current = (*j).GetTime ();
-      NS_ASSERT (current >= previous);
-    
-      if (previous >= plcpPayloadStart) 
-        {
-          psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
-                                                          noiseInterferenceW, 
-                                                          payloadMode), 
-                                            current - previous,
-                                            payloadMode);
-        } 
-      else if (previous >= plcpHeaderStart) 
-        {
-          if (current >= plcpPayloadStart) 
-            {
-              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
-                                                              noiseInterferenceW, 
-                                                              headerMode), 
-                                                plcpPayloadStart - previous,
-                                                headerMode);
-              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
-                                                              noiseInterferenceW, 
-                                                              payloadMode),
-                                                current - plcpPayloadStart,
-                                                payloadMode);
-            } 
-          else 
-            {
-              NS_ASSERT (current >= plcpHeaderStart);
-              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
-                                                              noiseInterferenceW, 
-                                                              headerMode), 
-                                                current - previous,
-                                                headerMode);
-            }
-        } 
-      else 
-        {
-          if (current >= plcpPayloadStart) 
-            {
-              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
-                                                              noiseInterferenceW, 
-                                                              headerMode), 
-                                                plcpPayloadStart - plcpHeaderStart,
-                                                headerMode);
-              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
-                                                              noiseInterferenceW, 
-                                                              payloadMode), 
-                                                current - plcpPayloadStart,
-                                                payloadMode);
-            } 
-          else if (current >= plcpHeaderStart) 
-            {
-              psr *= CalculateChunkSuccessRate (CalculateSnr (powerW, 
-                                                              noiseInterferenceW, 
-                                                              headerMode), 
-                                                current - plcpHeaderStart,
-                                                headerMode);
-            }
-        }
-
-      noiseInterferenceW += (*j).GetDelta ();
-      previous = (*j).GetTime ();
-      j++;
-    }
-
-  double per = 1 - psr;
-  return per;
-}
-
-
 void
-YansWifiPhy::EndSync (Ptr<Packet> packet, Ptr<RxEvent> event)
+YansWifiPhy::EndSync (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event)
 {
   NS_LOG_FUNCTION (this << packet << event);
   NS_ASSERT (IsStateSync ());
   NS_ASSERT (event->GetEndTime () == Simulator::Now ());
 
-  NiChanges ni;
-  double noiseInterferenceW = CalculateNoiseInterferenceW (event, &ni);
-  double snr = CalculateSnr (event->GetRxPowerW (),
-                             noiseInterferenceW,
-                             event->GetPayloadMode ());
+  struct InterferenceHelper::SnrPer snrPer;
+  snrPer = m_interference.CalculateSnrPer (event);
+
+  NS_LOG_DEBUG ("mode="<<(event->GetPayloadMode ().GetDataRate ())<<
+                ", snr="<<snrPer.snr<<", per="<<snrPer.per<<", size="<<packet->GetSize ());
   
-  /* calculate the SNIR at the start of the packet and accumulate
-   * all SNIR changes in the snir vector.
-   */
-  double per = CalculatePer (event, &ni);
-  NS_LOG_DEBUG ("mode="<<(event->GetPayloadMode ().GetDataRate ())<<
-                ", ber="<<(1-m_errorRateModel->GetChunkSuccessRate (event->GetPayloadMode (), snr, 1))<<
-                ", snr="<<snr<<", per="<<per<<", size="<<packet->GetSize ());
-  
-  if (m_random.GetValue () > per) 
+  if (m_random.GetValue () > snrPer.per) 
     {
-      m_state->SwitchFromSyncEndOk (packet, snr, event->GetPayloadMode (), event->GetPreambleType ());
+      m_state->SwitchFromSyncEndOk (packet, snrPer.snr, event->GetPayloadMode (), event->GetPreambleType ());
     } 
   else 
     {
       /* failure. */
-      m_state->SwitchFromSyncEndError (packet, snr);
+      m_state->SwitchFromSyncEndError (packet, snrPer.snr);
     }
 }
 
--- a/src/devices/wifi/yans-wifi-phy.h	Thu Jun 12 12:31:02 2008 -0700
+++ b/src/devices/wifi/yans-wifi-phy.h	Sat Jun 14 10:52:10 2008 -0700
@@ -21,8 +21,6 @@
 #ifndef YANS_WIFI_PHY_H
 #define YANS_WIFI_PHY_H
 
-#include <vector>
-#include <list>
 #include <stdint.h>
 #include "ns3/callback.h"
 #include "ns3/event-id.h"
@@ -36,6 +34,7 @@
 #include "wifi-mode.h"
 #include "wifi-preamble.h"
 #include "wifi-phy-standard.h"
+#include "interference-helper.h"
 
 
 namespace ns3 {
@@ -44,7 +43,6 @@
 class RxEvent;
 class YansWifiChannel;
 class WifiPhyStateHelper;
-class ErrorRateModel;
 
 
 /**
@@ -84,10 +82,14 @@
   void SetTxGain (double gain);
   void SetRxGain (double gain);
   void SetEdThreshold (double threshold);
+  void SetCcaMode1Threshold (double threshold);
+  void SetErrorRateModel (Ptr<ErrorRateModel> rate);
   double GetRxNoise (void) const;
   double GetTxGain (void) const;
   double GetRxGain (void) const;
   double GetEdThreshold (void) const;
+  double GetCcaMode1Threshold (void) const;
+  Ptr<ErrorRateModel> GetErrorRateModel (void) const;
 
 
   virtual double GetTxPowerStart (void) const;
@@ -112,24 +114,10 @@
   virtual Ptr<WifiChannel> GetChannel (void) const;
 
 private:
-  class NiChange {
-  public:
-    NiChange (Time time, double delta);
-    Time GetTime (void) const;
-    double GetDelta (void) const;
-    bool operator < (NiChange const &o) const;
-  private:
-    Time m_time;
-    double m_delta;
-  };
   typedef std::vector<WifiMode> Modes;
-  typedef std::list<Ptr<RxEvent> > Events;
-  typedef std::vector <NiChange> NiChanges;
 
 private:
   virtual void DoDispose (void);
-  void Configure80211aParameters (void);
-  void PrintModes (void) const;
   void Configure80211a (void);
   void ConfigureHolland (void);
   double GetEdThresholdW (void) const;
@@ -137,28 +125,14 @@
   double DbToRatio (double db) const;
   double WToDbm (double w) const;
   double RatioToDb (double ratio) const;
-  Time GetMaxPacketDuration (void) const;
   double GetPowerDbm (uint8_t power) const;
+  void EndSync (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event);
 
-  void AppendEvent (Ptr<RxEvent> event);
-  double CalculateNoiseInterferenceW (Ptr<RxEvent> event, NiChanges *ni) const;
-  double CalculateSnr (double signal, double noiseInterference, WifiMode mode) const;
-  double CalculateChunkSuccessRate (double snir, Time delay, WifiMode mode) const;
-  double CalculatePer (Ptr<const RxEvent> event, NiChanges *ni) const;
-  void EndSync (Ptr<Packet> packet, Ptr<RxEvent> event);
 private:
-  uint64_t m_txPrepareDelayUs;
-  uint64_t m_plcpLongPreambleDelayUs;
-  uint64_t m_plcpShortPreambleDelayUs;
-  WifiMode m_longPlcpHeaderMode;
-  WifiMode m_shortPlcpHeaderMode;
-  uint32_t m_plcpHeaderLength;
-  Time     m_maxPacketDuration;
-
-  double   m_edThresholdW; /* unit: W */
+  double   m_edThresholdW;
+  double   m_ccaMode1ThresholdW;
   double   m_txGainDb;
   double   m_rxGainDb;
-  double   m_rxNoiseRatio;
   double   m_txPowerBaseDbm;
   double   m_txPowerEndDbm;
   uint32_t m_nTxPower;
@@ -166,11 +140,10 @@
   Ptr<YansWifiChannel> m_channel;
   Modes m_modes;
   EventId m_endSyncEvent;
-  Events m_events;
   UniformVariable m_random;
   WifiPhyStandard m_standard;
   Ptr<WifiPhyStateHelper> m_state;
-  Ptr<ErrorRateModel> m_errorRateModel;
+  InterferenceHelper m_interference;
 };
 
 } // namespace ns3