rename WifiPhy to YansWifiPhy and add WifiPhy abstract base class.
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Wed, 11 Jun 2008 11:52:40 -0700
changeset 3888 a15618dcd0eb
parent 3887 51e9f5ef0963
child 3889 f35819202b66
rename WifiPhy to YansWifiPhy and add WifiPhy abstract base class.
examples/mixed-wireless.cc
examples/wifi-adhoc.cc
examples/wifi-ap.cc
src/devices/wifi/wifi-channel.cc
src/devices/wifi/wifi-channel.h
src/devices/wifi/wifi-phy-test.cc
src/devices/wifi/wifi-phy.cc
src/devices/wifi/wifi-phy.h
src/devices/wifi/wifi-test.cc
src/devices/wifi/wscript
src/devices/wifi/yans-wifi-phy.cc
src/devices/wifi/yans-wifi-phy.h
--- a/examples/mixed-wireless.cc	Wed Jun 11 11:15:43 2008 -0700
+++ b/examples/mixed-wireless.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -137,7 +137,7 @@
   //
   WifiHelper wifi;
   wifi.SetMac ("ns3::AdhocWifiMac");
-  wifi.SetPhy ("ns3::WifiPhy");
+  wifi.SetPhy ("ns3::YansWifiPhy");
   NetDeviceContainer backboneDevices = wifi.Install (backbone);
   //
   // Add the IPv4 protocol stack to the nodes in our container
@@ -246,7 +246,7 @@
       //
       WifiHelper wifiInfra;
       wifiInfra.SetMac ("ns3::AdhocWifiMac");
-      wifiInfra.SetPhy ("ns3::WifiPhy");
+      wifiInfra.SetPhy ("ns3::YansWifiPhy");
       NetDeviceContainer infraDevices = wifiInfra.Install (infra);
 
       // Add the IPv4 protocol stack to the nodes in our container
--- a/examples/wifi-adhoc.cc	Wed Jun 11 11:15:43 2008 -0700
+++ b/examples/wifi-adhoc.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -172,7 +172,7 @@
   GnuplotDataset dataset;
 
   wifi.SetMac ("ns3::AdhocWifiMac");
-  wifi.SetPhy ("ns3::WifiPhy");
+  wifi.SetPhy ("ns3::YansWifiPhy");
 
   NS_LOG_DEBUG ("54");
   experiment = Experiment ("54mb");
@@ -234,7 +234,7 @@
 
 
   gnuplot = Gnuplot ("rate-control.png");
-  Config::SetDefault ("ns3::WifiPhy::Standard", StringValue ("holland"));
+  Config::SetDefault ("ns3::YansWifiPhy::Standard", StringValue ("holland"));
 
 
   NS_LOG_DEBUG ("arf");
--- a/examples/wifi-ap.cc	Wed Jun 11 11:15:43 2008 -0700
+++ b/examples/wifi-ap.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -138,7 +138,7 @@
   channel->SetPropagationLossModel (log);
 
   Ssid ssid = Ssid ("wifi-default");
-  wifi.SetPhy ("ns3::WifiPhy");
+  wifi.SetPhy ("ns3::YansWifiPhy");
   wifi.SetRemoteStationManager ("ns3::ArfWifiManager");
   // setup stas.
   wifi.SetMac ("ns3::NqstaWifiMac", 
--- a/src/devices/wifi/wifi-channel.cc	Wed Jun 11 11:15:43 2008 -0700
+++ b/src/devices/wifi/wifi-channel.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -25,6 +25,7 @@
 #include "ns3/log.h"
 #include "ns3/pointer.h"
 #include "wifi-channel.h"
+#include "wifi-phy.h"
 #include "propagation-loss-model.h"
 #include "propagation-delay-model.h"
 
--- a/src/devices/wifi/wifi-channel.h	Wed Jun 11 11:15:43 2008 -0700
+++ b/src/devices/wifi/wifi-channel.h	Wed Jun 11 11:52:40 2008 -0700
@@ -27,13 +27,13 @@
 #include "ns3/net-device.h"
 #include "wifi-mode.h"
 #include "wifi-preamble.h"
-#include "wifi-phy.h"
 
 namespace ns3 {
 
 class NetDevice;
 class PropagationLossModel;
 class PropagationDelayModel;
+class WifiPhy;
 
 /**
  * \brief A 802.11 Channel
--- a/src/devices/wifi/wifi-phy-test.cc	Wed Jun 11 11:15:43 2008 -0700
+++ b/src/devices/wifi/wifi-phy-test.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -1,5 +1,6 @@
 #include "wifi-phy.h"
 #include "wifi-channel.h"
+#include "yans-wifi-phy.h"
 #include "propagation-loss-model.h"
 #include "propagation-delay-model.h"
 #include "ns3/ptr.h"
@@ -77,8 +78,8 @@
   Ptr<MobilityModel> posRx = CreateObject<StaticMobilityModel> ();
   posRx->SetPosition (Vector (m_input.distance, 0.0, 0.0));
 
-  Ptr<WifiPhy> tx = CreateObject<WifiPhy> ();
-  Ptr<WifiPhy> rx = CreateObject<WifiPhy> ();
+  Ptr<WifiPhy> tx = CreateObject<YansWifiPhy> ();
+  Ptr<WifiPhy> rx = CreateObject<YansWifiPhy> ();
   rx->SetReceiveOkCallback (MakeCallback (&PsrExperiment::Receive, this));
 
   Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
@@ -204,9 +205,9 @@
   Ptr<MobilityModel> posRx = CreateObject<StaticMobilityModel> ();
   posRx->SetPosition (Vector (0, 0.0, 0.0));
 
-  Ptr<WifiPhy> txA = CreateObject<WifiPhy> ();
-  Ptr<WifiPhy> txB = CreateObject<WifiPhy> ();
-  Ptr<WifiPhy> rx = CreateObject<WifiPhy> ();
+  Ptr<WifiPhy> txA = CreateObject<YansWifiPhy> ();
+  Ptr<WifiPhy> txB = CreateObject<YansWifiPhy> ();
+  Ptr<WifiPhy> rx = CreateObject<YansWifiPhy> ();
   rx->SetReceiveOkCallback (MakeCallback (&CollisionExperiment::Receive, this));
 
   Ptr<WifiChannel> channel = CreateObject<WifiChannel> ();
--- a/src/devices/wifi/wifi-phy.cc	Wed Jun 11 11:15:43 2008 -0700
+++ b/src/devices/wifi/wifi-phy.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -37,32 +37,32 @@
 
 namespace ns3 {
 
-  // Define all the WifiMode needed for 802.11a
-static WifiMode g_6mba = WifiModeFactory::CreateBpsk ("wifia-6mbs",
-                                                      true,
-                                                      20000000, 6000000, 12000000);
-static WifiMode g_9mba = WifiModeFactory::CreateBpsk ("wifia-9mbs",
-                                                      false,
-                                                      20000000, 9000000, 12000000);
+// Define all the WifiMode needed for 802.11a
+WifiMode WifiPhy::g_6mba = WifiModeFactory::CreateBpsk ("wifia-6mbs",
+                                                        true,
+                                                        20000000, 6000000, 12000000);
+WifiMode WifiPhy::g_9mba = WifiModeFactory::CreateBpsk ("wifia-9mbs",
+                                                        false,
+                                                        20000000, 9000000, 12000000);
 // XXX explain why Bpsk rather than Qpsk
-static WifiMode g_12mba = WifiModeFactory::CreateBpsk ("wifia-12mbs",
-                                                       true,
-                                                       20000000, 12000000, 24000000);
-static WifiMode g_18mba = WifiModeFactory::CreateBpsk ("wifia-18mbs",
-                                                       false,
-                                                       20000000, 18000000, 24000000);
-static WifiMode g_24mba = WifiModeFactory::CreateBpsk ("wifia-24mbs",
-                                                       true,
-                                                       20000000, 24000000, 48000000);
-static WifiMode g_36mba = WifiModeFactory::CreateBpsk ("wifia-36mbs",
-                                                       false,
-                                                       20000000, 36000000, 48000000);
-static WifiMode g_48mba = WifiModeFactory::CreateBpsk ("wifia-48mbs",
-                                                       false,
-                                                       20000000, 48000000, 72000000);
-static WifiMode g_54mba = WifiModeFactory::CreateBpsk ("wifia-54mbs",
-                                                       false,
-                                                       20000000, 54000000, 72000000);
+WifiMode WifiPhy::g_12mba = WifiModeFactory::CreateBpsk ("wifia-12mbs",
+                                                         true,
+                                                         20000000, 12000000, 24000000);
+WifiMode WifiPhy::g_18mba = WifiModeFactory::CreateBpsk ("wifia-18mbs",
+                                                         false,
+                                                         20000000, 18000000, 24000000);
+WifiMode WifiPhy::g_24mba = WifiModeFactory::CreateBpsk ("wifia-24mbs",
+                                                         true,
+                                                         20000000, 24000000, 48000000);
+WifiMode WifiPhy::g_36mba = WifiModeFactory::CreateBpsk ("wifia-36mbs",
+                                                         false,
+                                                         20000000, 36000000, 48000000);
+WifiMode WifiPhy::g_48mba = WifiModeFactory::CreateBpsk ("wifia-48mbs",
+                                                         false,
+                                                         20000000, 48000000, 72000000);
+WifiMode WifiPhy::g_54mba = WifiModeFactory::CreateBpsk ("wifia-54mbs",
+                                                         false,
+                                                         20000000, 54000000, 72000000);
 
 
 /****************************************************************
@@ -72,106 +72,6 @@
 WifiPhyListener::~WifiPhyListener ()
 {}
 
-
-/****************************************************************
- *       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.
- ****************************************************************/
-
-WifiPhy::NiChange::NiChange (Time time, double delta)
-  : m_time (time), m_delta (delta) 
-{}
-Time
-WifiPhy::NiChange::GetTime (void) const
-{
-  return m_time;
-}
-double 
-WifiPhy::NiChange::GetDelta (void) const
-{
-  return m_delta;
-}
-bool 
-WifiPhy::NiChange::operator < (WifiPhy::NiChange const &o) const
-{
-  return (m_time < o.m_time)?true:false;
-}
-
-
-
 /****************************************************************
  *       The actual WifiPhy class
  ****************************************************************/
@@ -183,82 +83,11 @@
 {
   static TypeId tid = TypeId ("ns3::WifiPhy")
     .SetParent<Object> ()
-    .AddConstructor<WifiPhy> ()
-    .AddAttribute ("EnergyDetectionThreshold",
-                   "The energy of a received signal should be higher than "
-                   "this threshold (dbm) to allow the PHY layer to detect the signal.",
-                   DoubleValue (-140.0),
-                   MakeDoubleAccessor (&WifiPhy::SetEdThreshold,
-                                       &WifiPhy::GetEdThreshold),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("TxGain",
-                   "Transmission gain (dB).",
-                   DoubleValue (1.0),
-                   MakeDoubleAccessor (&WifiPhy::SetTxGain,
-                                       &WifiPhy::GetTxGain),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("RxGain",
-                   "Reception gain (dB).",
-                   DoubleValue (1.0),
-                   MakeDoubleAccessor (&WifiPhy::SetRxGain,
-                                       &WifiPhy::GetRxGain),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("TxPowerLevels",
-                   "Number of transmission power levels available between "
-                   "TxPowerBase and TxPowerEnd included.",
-                   UintegerValue (1),
-                   MakeUintegerAccessor (&WifiPhy::m_nTxPower),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("TxPowerEnd",
-                   "Maximum available transmission level (dbm).",
-                   DoubleValue (16.0206),
-                   MakeDoubleAccessor (&WifiPhy::SetTxPowerEnd, 
-                                       &WifiPhy::GetTxPowerEnd),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("TxPowerStart",
-                   "Minimum available transmission level (dbm).",
-                   DoubleValue (16.0206),
-                   MakeDoubleAccessor (&WifiPhy::SetTxPowerStart, 
-                                       &WifiPhy::GetTxPowerStart),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("RxNoise",
-                   "Ratio of energy lost by receiver (dB).",
-                   DoubleValue (7),
-                   MakeDoubleAccessor (&WifiPhy::SetRxNoise,
-                                       &WifiPhy::GetRxNoise),
-                   MakeDoubleChecker<double> ())
-    .AddAttribute ("Standard", "The standard chosen configures a set of transmission modes"
-                   " and some PHY-specific constants.",
-                   EnumValue (WIFI_PHY_STANDARD_80211a),
-                   MakeEnumAccessor (&WifiPhy::SetStandard),
-                   MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a",
-                                    WIFI_PHY_STANDARD_holland, "holland"))
-    .AddTraceSource ("State",
-                     "The WifiPhy state",
-                     MakeTraceSourceAccessor (&WifiPhy::m_stateLogger))
-    .AddTraceSource ("RxOk",
-                     "A packet has been received successfully.",
-                     MakeTraceSourceAccessor (&WifiPhy::m_rxOkTrace))
-    .AddTraceSource ("RxError",
-                     "A packet has been received unsuccessfully.",
-                     MakeTraceSourceAccessor (&WifiPhy::m_rxErrorTrace))
-    .AddTraceSource ("Tx", "Packet transmission is starting.",
-                     MakeTraceSourceAccessor (&WifiPhy::m_txTrace))
     ;
   return tid;
 }
 
 WifiPhy::WifiPhy ()
-  : m_syncing (false),
-    m_endTx (Seconds (0)),
-    m_endSync (Seconds (0)),
-    m_endCcaBusy (Seconds (0)),
-    m_startTx (Seconds (0)),
-    m_startSync (Seconds (0)),
-    m_startCcaBusy (Seconds (0)),
-    m_previousStateChangeTime (Seconds (0)),
-    m_endSyncEvent (),
-    m_random (0.0, 1.0)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -268,1130 +97,4 @@
   NS_LOG_FUNCTION (this);
 }
 
-void
-WifiPhy::DoDispose (void)
-{
-  NS_LOG_FUNCTION (this);
-  m_channel = 0;
-  m_events.clear ();
-  m_modes.clear ();
-}
-
-void
-WifiPhy::SetStandard (enum WifiPhyStandard standard)
-{
-  NS_LOG_FUNCTION (this << standard);
-  m_standard = standard;
-  switch (standard) {
-  case WIFI_PHY_STANDARD_80211a:
-    Configure80211a ();
-    break;
-  case WIFI_PHY_STANDARD_holland:
-    ConfigureHolland ();
-    break;
-  default:
-    NS_ASSERT (false);
-    break;
-  }
-}
-
-
-void 
-WifiPhy::SetRxNoise (double db)
-{
-  NS_LOG_FUNCTION (this << db);
-  m_rxNoiseRatio = DbToRatio (db);
-}
-void 
-WifiPhy::SetTxPowerStart (double start)
-{
-  NS_LOG_FUNCTION (this << start);
-  m_txPowerBaseDbm = start;
-}
-void 
-WifiPhy::SetTxPowerEnd (double end)
-{
-  NS_LOG_FUNCTION (this << end);
-  m_txPowerEndDbm = end;
-}
-void 
-WifiPhy::SetNTxPower (uint32_t n)
-{
-  NS_LOG_FUNCTION (this << n);
-  m_nTxPower = n;
-}
-void 
-WifiPhy::SetTxGain (double gain)
-{
-  NS_LOG_FUNCTION (this << gain);
-  m_txGainDb = gain;
-}
-void 
-WifiPhy::SetRxGain (double gain)
-{
-  NS_LOG_FUNCTION (this << gain);
-  m_rxGainDb = gain;
-}
-void 
-WifiPhy::SetEdThreshold (double threshold)
-{
-  NS_LOG_FUNCTION (this << threshold);
-  m_edThresholdW = DbmToW (threshold);
-}
-double 
-WifiPhy::GetRxNoise (void) const
-{
-  return RatioToDb (m_rxNoiseRatio);
-}
-double 
-WifiPhy::GetTxPowerStart (void) const
-{
-  return m_txPowerBaseDbm;
-}
-double 
-WifiPhy::GetTxPowerEnd (void) const
-{
-  return m_txPowerEndDbm;
-}
-double 
-WifiPhy::GetTxGain (void) const
-{
-  return m_txGainDb;
-}
-double 
-WifiPhy::GetRxGain (void) const
-{
-  return m_rxGainDb;
-}
-
-double 
-WifiPhy::GetEdThreshold (void) const
-{
-  return WToDbm (m_edThresholdW);
-}
-
-Ptr<WifiChannel> 
-WifiPhy::GetChannel (void) const
-{
-  return m_channel;
-}
-
-void 
-WifiPhy::SetChannel (Ptr<WifiChannel> channel)
-{
-  m_channel = channel;
-}
-
-void 
-WifiPhy::SetReceiveOkCallback (SyncOkCallback callback)
-{
-  m_syncOkCallback = callback;
-}
-void 
-WifiPhy::SetReceiveErrorCallback (SyncErrorCallback callback)
-{
-  m_syncErrorCallback = callback;
-}
-void 
-WifiPhy::StartReceivePacket (Ptr<Packet> packet, 
-                             double rxPowerDbm,
-                             WifiMode txMode,
-                             enum WifiPreamble preamble)
-{
-  NS_LOG_FUNCTION (this << packet << rxPowerDbm << txMode << preamble);
-  rxPowerDbm += m_rxGainDb;
-  double rxPowerW = DbmToW (rxPowerDbm);
-  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);
-
-  switch (GetState ()) {
-  case WifiPhy::SYNC:
-    NS_LOG_DEBUG ("drop packet because already in Sync (power="<<
-                  rxPowerW<<"W)");
-    if (endRx > m_endSync) 
-      {
-        goto maybeCcaBusy;
-      }
-    break;
-  case WifiPhy::TX:
-    NS_LOG_DEBUG ("drop packet because already in Tx (power="<<
-                  rxPowerW<<"W)");
-    if (endRx > m_endTx) 
-      {
-        goto maybeCcaBusy;
-      }
-    break;
-  case WifiPhy::CCA_BUSY:
-  case WifiPhy::IDLE:
-    if (rxPowerW > m_edThresholdW) 
-      {
-        NS_LOG_DEBUG ("sync (power="<<rxPowerW<<"W)");
-        // sync to signal
-        NotifySyncStart (rxDuration);
-        SwitchToSync (rxDuration);
-        NS_ASSERT (m_endSyncEvent.IsExpired ());
-        m_endSyncEvent = Simulator::Schedule (rxDuration, &WifiPhy::EndSync, this, 
-                                              packet,
-                                              event);
-      }
-    else 
-      {
-        NS_LOG_DEBUG ("drop packet because signal power too Small ("<<
-                      rxPowerW<<"<"<<m_edThresholdW<<")");
-        goto maybeCcaBusy;
-      }
-    break;
-  }
-
-  return;
-
- maybeCcaBusy:
-
-  if (rxPowerW > m_edThresholdW) 
-    {
-      SwitchMaybeToCcaBusy (rxDuration);
-      NotifyCcaBusyStart (rxDuration);
-    } 
-  else 
-    {
-      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 ();
-          SwitchMaybeToCcaBusy (delta);
-          NotifyCcaBusyStart (delta);
-        }
-    }
-
-}
-void 
-WifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower)
-{
-  NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txPower);
-  /* Transmission can happen if:
-   *  - we are syncing on a packet. It is the responsability of the
-   *    MAC layer to avoid doing this but the PHY does nothing to 
-   *    prevent it.
-   *  - we are idle
-   */
-  NS_ASSERT (!IsStateTx ());
-
-  m_txTrace (packet, txMode, preamble, txPower);
-  Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
-  NotifyTxStart (txDuration);
-  SwitchToTx (txDuration);
-  m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
-}
-
-uint32_t 
-WifiPhy::GetNModes (void) const
-{
-  return m_modes.size ();
-}
-WifiMode 
-WifiPhy::GetMode (uint32_t mode) const
-{
-  return m_modes[mode];
-}
-uint32_t 
-WifiPhy::GetNTxPower (void) const
-{
-  return m_nTxPower;
-}
-
-double 
-WifiPhy::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 - GetChunkSuccessRate (txMode, middle, 1)) > ber) 
-        {
-          low = middle;
-        } 
-      else 
-        {
-          high = middle;
-        }
-    }
-  return low;
-}
-
-void
-WifiPhy::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
-WifiPhy::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-GetChunkSuccessRate (mode,snr, 2000*8);
-      std::cout <<ber<< " ";
-    }
-    std::cout << std::endl;
-  }
-#endif
-}
-
-void
-WifiPhy::Configure80211a (void)
-{
-  NS_LOG_FUNCTION (this);
-  Configure80211aParameters ();
-  m_modes.push_back (g_6mba);
-  m_modes.push_back (g_9mba);
-  m_modes.push_back (g_12mba);
-  m_modes.push_back (g_18mba);
-  m_modes.push_back (g_24mba);
-  m_modes.push_back (g_36mba);
-  m_modes.push_back (g_48mba);
-  m_modes.push_back (g_54mba);
-
-  PrintModes ();
-}
-
-void
-WifiPhy::ConfigureHolland (void)
-{
-  NS_LOG_FUNCTION (this);
-  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 
-WifiPhy::RegisterListener (WifiPhyListener *listener)
-{
-  m_listeners.push_back (listener);
-}
-
-bool 
-WifiPhy::IsStateCcaBusy (void)
-{
-  return GetState () == CCA_BUSY;
-}
-
-bool 
-WifiPhy::IsStateIdle (void)
-{
-  return (GetState () == IDLE)?true:false;
-}
-bool 
-WifiPhy::IsStateBusy (void)
-{
-  return (GetState () != IDLE)?true:false;
-}
-bool 
-WifiPhy::IsStateSync (void)
-{
-  return (GetState () == SYNC)?true:false;
-}
-bool 
-WifiPhy::IsStateTx (void)
-{
-  return (GetState () == TX)?true:false;
-}
-
-Time
-WifiPhy::GetStateDuration (void)
-{
-  return Simulator::Now () - m_previousStateChangeTime;
-}
-Time
-WifiPhy::GetDelayUntilIdle (void)
-{
-  Time retval;
-
-  switch (GetState ()) {
-  case SYNC:
-    retval = m_endSync - Simulator::Now ();
-    break;
-  case TX:
-    retval = m_endTx - Simulator::Now ();
-    break;
-  case CCA_BUSY:
-    retval = m_endCcaBusy - Simulator::Now ();
-    break;
-  case IDLE:
-    retval = Seconds (0);
-    break;
-  default:
-    NS_ASSERT (false);
-    // NOTREACHED
-    retval = Seconds (0);
-    break;
-  }
-  retval = Max (retval, Seconds (0));
-  return retval;
-}
-
-Time 
-WifiPhy::GetLastRxStartTime (void) const
-{
-  return m_startSync;
-}
-
-
-Time
-WifiPhy::CalculateTxDuration (uint32_t size, WifiMode payloadMode, 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);
-}
-
-char const *
-WifiPhy::StateToString (enum State state)
-{
-  switch (state) {
-  case TX:
-    return "TX";
-    break;
-  case CCA_BUSY:
-    return "CCA_BUSY";
-    break;
-  case IDLE:
-    return "IDLE";
-    break;
-  case SYNC:
-    return "SYNC";
-    break;
-  default:
-    NS_ASSERT (false);
-    // quiet compiler
-    return "INVALID";
-    break;
-  }
-}
-enum WifiPhy::State 
-WifiPhy::GetState (void)
-{
-  if (m_endTx > Simulator::Now ()) 
-    {
-      return WifiPhy::TX;
-    } 
-  else if (m_syncing) 
-    {
-      return WifiPhy::SYNC;
-    } 
-  else if (m_endCcaBusy > Simulator::Now ()) 
-    {
-      return WifiPhy::CCA_BUSY;
-    } 
-  else 
-    {
-      return WifiPhy::IDLE;
-    }
-}
-
-double 
-WifiPhy::DbToRatio (double dB) const
-{
-  double ratio = pow(10.0,dB/10.0);
-  return ratio;
-}
-
-double 
-WifiPhy::DbmToW (double dBm) const
-{
-  double mW = pow(10.0,dBm/10.0);
-  return mW / 1000.0;
-}
-
-double
-WifiPhy::WToDbm (double w) const
-{
-  return 10.0 * log10(w * 1000.0);
-}
-
-double
-WifiPhy::RatioToDb (double ratio) const
-{
-  return 10.0 * log10(ratio);
-}
-
-double
-WifiPhy::GetEdThresholdW (void) const
-{
-  return m_edThresholdW;
-}
-
-Time
-WifiPhy::GetMaxPacketDuration (void) const
-{
-  return m_maxPacketDuration;
-}
-
-double 
-WifiPhy::GetPowerDbm (uint8_t power) const
-{
-  NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm);
-  NS_ASSERT (m_nTxPower > 0);
-  double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / m_nTxPower;
-  return dbm;
-}
-
-void 
-WifiPhy::NotifyTxStart (Time duration)
-{
-  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
-    (*i)->NotifyTxStart (duration);
-  }
-}
-void 
-WifiPhy::NotifySyncStart (Time duration)
-{
-  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
-    (*i)->NotifyRxStart (duration);
-  }
-}
-void 
-WifiPhy::NotifySyncEndOk (void)
-{
-  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
-    (*i)->NotifyRxEndOk ();
-  }
-}
-void 
-WifiPhy::NotifySyncEndError (void)
-{
-  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
-    (*i)->NotifyRxEndError ();
-  }
-}
-void 
-WifiPhy::NotifyCcaBusyStart (Time duration)
-{
-  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
-    (*i)->NotifyCcaBusyStart (duration);
-  }
-}
-
-void
-WifiPhy::LogPreviousIdleAndCcaBusyStates (void)
-{
-  Time now = Simulator::Now ();
-  Time idleStart = Max (m_endCcaBusy, m_endSync);
-  idleStart = Max (idleStart, m_endTx);
-  NS_ASSERT (idleStart <= now);
-  if (m_endCcaBusy > m_endSync && 
-      m_endCcaBusy > m_endTx) {
-    Time ccaBusyStart = Max (m_endTx, m_endSync);
-    ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy);
-    m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, WifiPhy::CCA_BUSY);
-  }
-  m_stateLogger (idleStart, now - idleStart, WifiPhy::IDLE);
-}
-
-void
-WifiPhy::SwitchToTx (Time txDuration)
-{
-  Time now = Simulator::Now ();
-  switch (GetState ()) {
-  case WifiPhy::SYNC:
-    /* The packet which is being received as well
-     * as its endSync event are cancelled by the caller.
-     */
-    m_syncing = false;
-    m_stateLogger (m_startSync, now - m_startSync, WifiPhy::SYNC);
-    m_endSyncEvent.Cancel ();
-    m_endSync = now;
-    break;
-  case WifiPhy::CCA_BUSY: {
-    Time ccaStart = Max (m_endSync, m_endTx);
-    ccaStart = Max (ccaStart, m_startCcaBusy);
-    m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
-  } break;
-  case WifiPhy::IDLE:
-    LogPreviousIdleAndCcaBusyStates ();
-    break;
-  default:
-    NS_ASSERT (false);
-    break;
-  }
-  m_stateLogger (now, txDuration, WifiPhy::TX);
-  m_previousStateChangeTime = now;
-  m_endTx = now + txDuration;
-  m_startTx = now;
-}
-void
-WifiPhy::SwitchToSync (Time rxDuration)
-{
-  NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
-  NS_ASSERT (!m_syncing);
-  Time now = Simulator::Now ();
-  switch (GetState ()) {
-  case WifiPhy::IDLE:
-    LogPreviousIdleAndCcaBusyStates ();
-    break;
-  case WifiPhy::CCA_BUSY: {
-    Time ccaStart = Max (m_endSync, m_endTx);
-    ccaStart = Max (ccaStart, m_startCcaBusy);
-    m_stateLogger (ccaStart, now - ccaStart, WifiPhy::CCA_BUSY);
-  } break;
-  case WifiPhy::SYNC:
-  case WifiPhy::TX:
-    NS_ASSERT (false);
-    break;
-  }
-  m_previousStateChangeTime = now;
-  m_syncing = true;
-  m_startSync = now;
-  m_endSync = now + rxDuration;
-  NS_ASSERT (IsStateSync ());
-}
-void
-WifiPhy::SwitchFromSync (void)
-{
-  NS_ASSERT (IsStateSync ());
-  NS_ASSERT (m_syncing);
-
-  Time now = Simulator::Now ();
-  m_stateLogger (m_startSync, now - m_startSync, WifiPhy::SYNC);
-  m_previousStateChangeTime = now;
-  m_syncing = false;
-
-  NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
-}
-void
-WifiPhy::SwitchMaybeToCcaBusy (Time duration)
-{
-  Time now = Simulator::Now ();
-  switch (GetState ()) {
-  case WifiPhy::IDLE:
-    LogPreviousIdleAndCcaBusyStates ();
-  break;
-  case WifiPhy::CCA_BUSY:
-    break;
-  case WifiPhy::SYNC:
-    break;
-  case WifiPhy::TX:
-    break;
-  }
-  m_startCcaBusy = now;
-  m_endCcaBusy = Max (m_endCcaBusy, now + duration);
-}
-
-void 
-WifiPhy::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);
-}
-
-
-
-/**
- * Stuff specific to the BER model here.
- */
-double 
-WifiPhy::Log2 (double val) const
-{
-  return log(val) / log(2.0);
-}
-double 
-WifiPhy::GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const
-{
-  double EbNo = snr * signalSpread / phyRate;
-  double z = sqrt(EbNo);
-  double ber = 0.5 * erfc(z);
-  NS_LOG_INFO ("bpsk snr="<<snr<<" ber="<<ber);
-  return ber;
-}
-double 
-WifiPhy::GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const
-{
-  double EbNo = snr * signalSpread / phyRate;
-  double z = sqrt ((1.5 * Log2 (m) * EbNo) / (m - 1.0));
-  double z1 = ((1.0 - 1.0 / sqrt (m)) * erfc (z)) ;
-  double z2 = 1 - pow ((1-z1), 2.0);
-  double ber = z2 / Log2 (m);
-  NS_LOG_INFO ("Qam m="<<m<<" rate=" << phyRate << " snr="<<snr<<" ber="<<ber);
-  return ber;
-}
-uint32_t
-WifiPhy::Factorial (uint32_t k) const
-{
-  uint32_t fact = 1;
-  while (k > 0) 
-    {
-      fact *= k;
-      k--;
-    }
-  return fact;
-}
-double 
-WifiPhy::Binomial (uint32_t k, double p, uint32_t n) const
-{
-  double retval = Factorial (n) / (Factorial (k) * Factorial (n-k)) * pow (p, k) * pow (1-p, n-k);
-  return retval;
-}
-double 
-WifiPhy::CalculatePdOdd (double ber, unsigned int d) const
-{
-  NS_ASSERT ((d % 2) == 1);
-  unsigned int dstart = (d + 1) / 2;
-  unsigned int dend = d;
-  double pd = 0;
-
-  for (unsigned int i = dstart; i < dend; i++) 
-    {
-      pd += Binomial (i, ber, d);
-    }
-  return pd;
-}
-double 
-WifiPhy::CalculatePdEven (double ber, unsigned int d) const
-{
-  NS_ASSERT ((d % 2) == 0);
-  unsigned int dstart = d / 2 + 1;
-  unsigned int dend = d;
-  double pd = 0;
-
-  for (unsigned int i = dstart; i < dend; i++)
-    {
-      pd +=  Binomial (i, ber, d);
-    }
-  pd += 0.5 * Binomial (d / 2, ber, d);
-
-  return pd;
-}
-
-double 
-WifiPhy::CalculatePd (double ber, unsigned int d) const
-{
-  double pd;
-  if ((d % 2) == 0) 
-    {
-      pd = CalculatePdEven (ber, d);
-    } 
-  else 
-    {
-      pd = CalculatePdOdd (ber, d);
-    }
-  return pd;
-}
-
-double
-WifiPhy::GetFecBpskBer (double snr, double nbits, 
-                         uint32_t signalSpread, uint32_t phyRate,
-                         uint32_t dFree, uint32_t adFree) const
-{
-  double ber = GetBpskBer (snr, signalSpread, phyRate);
-  if (ber == 0.0) 
-    {
-      return 1.0;
-    }
-  double pd = CalculatePd (ber, dFree);
-  double pmu = adFree * pd;
-  pmu = std::min (pmu, 1.0);
-  double pms = pow (1 - pmu, nbits);
-  return pms;
-}
-
-double
-WifiPhy::GetFecQamBer (double snr, uint32_t nbits, 
-                       uint32_t signalSpread,
-                       uint32_t phyRate,
-                       uint32_t m, uint32_t dFree,
-                       uint32_t adFree, uint32_t adFreePlusOne) const
-{
-  double ber = GetQamBer (snr, m, signalSpread, phyRate);
-  if (ber == 0.0) 
-    {
-      return 1.0;
-    }
-  /* first term */
-  double pd = CalculatePd (ber, dFree);
-  double pmu = adFree * pd;
-  /* second term */
-  pd = CalculatePd (ber, dFree + 1);
-  pmu += adFreePlusOne * pd;
-  pmu = std::min (pmu, 1.0);
-  double pms = pow (1 - pmu, nbits);
-  return pms;
-}
-
-double 
-WifiPhy::GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const
-{
-  if (mode.GetUid () == g_6mba.GetUid ())
-    {
-      return GetFecBpskBer (snr, 
-                            nbits,
-                            mode.GetBandwidth (), // signal spread
-                            mode.GetPhyRate (), // phy rate
-                            10, // dFree
-                            11 // adFree
-                            );      
-    }
-  else if (mode.GetUid () == g_9mba.GetUid ())
-    {
-      return GetFecBpskBer (snr, 
-                            nbits,
-                            mode.GetBandwidth (), // signal spread
-                            mode.GetPhyRate (), // phy rate
-                            5, // dFree
-                            8 // adFree
-                            );
-    }
-  else if (mode.GetUid () == g_12mba.GetUid ())
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           4,  // m 
-                           10, // dFree
-                           11, // adFree
-                           0   // adFreePlusOne
-                           );
-    }
-  else if (mode.GetUid () == g_18mba.GetUid ())
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           4, // m
-                           5, // dFree
-                           8, // adFree
-                           31 // adFreePlusOne
-                           );
-    }
-  else if (mode.GetUid () == g_24mba.GetUid ())
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           16, // m
-                           10, // dFree
-                           11, // adFree
-                           0   // adFreePlusOne
-                           );
-    }
-  else if (mode.GetUid () == g_36mba.GetUid ())
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           16, // m
-                           5,  // dFree
-                           8,  // adFree
-                           31  // adFreePlusOne
-                           );
-    }
-  else if (mode.GetUid () == g_48mba.GetUid ())
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           64, // m
-                           6,  // dFree
-                           1,  // adFree
-                           16  // adFreePlusOne
-                           );
-    }
-  else if (mode.GetUid () == g_54mba.GetUid ())
-    {
-      return GetFecQamBer (snr, 
-                           nbits,
-                           mode.GetBandwidth (), // signal spread
-                           mode.GetPhyRate (), // phy rate
-                           64, // m
-                           5,  // dFree
-                           8,  // adFree
-                           31  // adFreePlusOne
-                           );
-    }
-  return 0;
-}
-
-double
-WifiPhy::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
-WifiPhy::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
-WifiPhy::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 = GetChunkSuccessRate (mode, snir, (uint32_t)nbits);
-  return csr;
-}
-
-double 
-WifiPhy::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
-WifiPhy::EndSync (Ptr<Packet> packet, Ptr<RxEvent> 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 ());
-  
-  /* 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-GetChunkSuccessRate (event->GetPayloadMode (), snr, 1))<<
-                ", snr="<<snr<<", per="<<per<<", size="<<packet->GetSize ());
-  
-  if (m_random.GetValue () > per) 
-    {
-      NotifySyncEndOk ();
-      SwitchFromSync ();
-      m_rxOkTrace (packet, snr, event->GetPayloadMode (), event->GetPreambleType ());
-      if (!m_syncOkCallback.IsNull ())
-        {
-          m_syncOkCallback (packet, snr, event->GetPayloadMode (), event->GetPreambleType ());
-        }
-    } 
-  else 
-    {
-      /* failure. */
-      NotifySyncEndError ();
-      SwitchFromSync ();
-      m_rxErrorTrace (packet, snr);
-      if (!m_syncErrorCallback.IsNull ())
-        {
-          m_syncErrorCallback (packet, snr);
-        }
-    }
-}
-
-
-
-
 } // namespace ns3
--- a/src/devices/wifi/wifi-phy.h	Wed Jun 11 11:15:43 2008 -0700
+++ b/src/devices/wifi/wifi-phy.h	Wed Jun 11 11:52:40 2008 -0700
@@ -39,10 +39,6 @@
 
 namespace ns3 {
 
-class RandomUniform;
-class RxEvent;
-class TraceContainer;
-class WifiNetDevice;
 class WifiChannel;
 
 /**
@@ -93,16 +89,6 @@
 /**
  * \brief 802.11 PHY layer model
  *
- * This PHY implements a model of 802.11a. The model
- * implemented here is based on the model described
- * in "Yet Another Network Simulator", 
- * (http://cutebugs.net/files/wns2-yans.pdf).
- *
- *
- * This PHY model depends on a channel loss and delay
- * model as provided by the ns3::PropagationLossModel
- * and ns3::PropagationDelayModel classes, both of which are
- * members of the ns3::WifiChannel class.
  */
 class WifiPhy : public Object
 {
@@ -147,40 +133,28 @@
   WifiPhy ();
   virtual ~WifiPhy ();
 
-  void SetStandard (enum WifiPhyStandard standard);
-  void SetRxNoise (double ratio);
-  void SetTxPowerStart (double start);
-  void SetTxPowerEnd (double end);
-  void SetNTxPower (uint32_t n);
-  void SetTxGain (double gain);
-  void SetRxGain (double gain);
-  void SetEdThreshold (double threshold);
-  double GetRxNoise (void) const;
-  double GetTxPowerStart (void) const;
-  double GetTxPowerEnd (void) const;
+  virtual double GetTxPowerStart (void) const = 0;
+  virtual double GetTxPowerEnd (void) const = 0;
   /**
    * \returns the number of tx power levels available for this PHY.
    */
-  uint32_t GetNTxPower (void) const;
-  double GetTxGain (void) const;
-  double GetRxGain (void) const;
-  double GetEdThreshold (void) const;
+  virtual uint32_t GetNTxPower (void) const = 0;
 
   /**
    * \param channel the channel to connect to.
    */
-  void SetChannel (Ptr<WifiChannel> channel);
+  virtual void SetChannel (Ptr<WifiChannel> channel) = 0;
 
   /**
    * \param callback the callback to invoke
    *        upon successful packet reception.
    */
-  void SetReceiveOkCallback (SyncOkCallback callback);
+  virtual void SetReceiveOkCallback (SyncOkCallback callback) = 0;
   /**
    * \param callback the callback to invoke
    *        upon erronous packet reception.
    */
-  void SetReceiveErrorCallback (SyncErrorCallback callback);
+  virtual void SetReceiveErrorCallback (SyncErrorCallback callback) = 0;
 
   /**
    * \param packet the packet to send
@@ -189,7 +163,7 @@
    * \param txPowerLevel a power level to use to send this packet. The real
    *        transmission power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
    */
-  void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel);
+  virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel) = 0;
 
   /**
    * \param listener the new listener
@@ -197,41 +171,41 @@
    * Add the input listener to the list of objects to be notified of
    * PHY-level events.
    */
-  void RegisterListener (WifiPhyListener *listener);
+  virtual void RegisterListener (WifiPhyListener *listener) = 0;
 
   /**
    * \returns true of the current state of the PHY layer is WifiPhy:LCCA_BUSY, false otherwise.
    */
-  bool IsStateCcaBusy (void);
+  virtual bool IsStateCcaBusy (void) = 0;
   /**
    * \returns true of the current state of the PHY layer is WifiPhy::IDLE, false otherwise.
    */
-  bool IsStateIdle (void);
+  virtual bool IsStateIdle (void) = 0;
   /**
    * \returns true of the current state of the PHY layer is not WifiPhy::IDLE, false otherwise.
    */
-  bool IsStateBusy (void);
+  virtual bool IsStateBusy (void) = 0;
   /**
    * \returns true of the current state of the PHY layer is WifiPhy::SYNC, false otherwise.
    */
-  bool IsStateSync (void);
+  virtual bool IsStateSync (void) = 0;
   /**
    * \returns true of the current state of the PHY layer is WifiPhy::TX, false otherwise.
    */
-  bool IsStateTx (void);
+  virtual bool IsStateTx (void) = 0;
   /**
    * \returns the amount of time since the current state has started.
    */
-  Time GetStateDuration (void);
+  virtual Time GetStateDuration (void) = 0;
   /**
    * \returns the predicted delay until this PHY can become WifiPhy::IDLE.
    *
    * The PHY will never become WifiPhy::IDLE _before_ the delay returned by
    * this method but it could become really idle later.
    */
-  Time GetDelayUntilIdle (void);
+  virtual Time GetDelayUntilIdle (void) = 0;
 
-  Time GetLastRxStartTime (void) const;
+  virtual Time GetLastRxStartTime (void) const = 0;
 
   /**
    * \param size the number of bytes in the packet to send
@@ -240,17 +214,17 @@
    * \returns the total amount of time this PHY will stay busy for
    *          the transmission of these bytes.
    */
-  Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const;
+  virtual Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const = 0;
 
   /**
    * \returns the number of transmission modes supported by this PHY.
    */
-  uint32_t GetNModes (void) const;
+  virtual uint32_t GetNModes (void) const = 0;
   /**
    * \param mode index in array of supported modes
    * \returns the mode whose index is specified.
    */
-  WifiMode GetMode (uint32_t mode) const;
+  virtual WifiMode GetMode (uint32_t mode) const = 0;
   /* return snr: W/W */
   /**
    * \param txMode the transmission mode
@@ -258,122 +232,24 @@
    * \returns the minimum snr which is required to achieve
    *          the requested ber for the specified transmission mode.
    */
-  double CalculateSnr (WifiMode txMode, double ber) const;
+  virtual double CalculateSnr (WifiMode txMode, double ber) const = 0;
 
   /* rxPower unit is Watt */
-  void StartReceivePacket (Ptr<Packet> packet,
-                           double rxPowerDbm,
-                           WifiMode mode,
-                           WifiPreamble preamble);
-
-  Ptr<WifiChannel> GetChannel (void) const;
+  virtual void StartReceivePacket (Ptr<Packet> packet,
+                                   double rxPowerDbm,
+                                   WifiMode mode,
+                                   WifiPreamble preamble) = 0;
 
-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<WifiPhyListener *> Listeners;
-  typedef std::list<Ptr<RxEvent> > Events;
-  typedef std::vector <NiChange> NiChanges;
+  virtual Ptr<WifiChannel> GetChannel (void) const = 0;
 
-private:
-  virtual void DoDispose (void);
-  void Configure80211aParameters (void);
-  void PrintModes (void) const;
-  void Configure80211a (void);
-  void ConfigureHolland (void);
-  char const *StateToString (enum State state);
-  enum WifiPhy::State GetState (void);
-  double GetEdThresholdW (void) const;
-  double DbmToW (double dbm) const;
-  double DbToRatio (double db) const;
-  double WToDbm (double w) const;
-  double RatioToDb (double ratio) const;
-  Time GetMaxPacketDuration (void) const;
-  void CancelRx (void);
-  double GetPowerDbm (uint8_t power) const;
-  void NotifyTxStart (Time duration);
-  void NotifyWakeup (void);
-  void NotifySyncStart (Time duration);
-  void NotifySyncEndOk (void);
-  void NotifySyncEndError (void);
-  void NotifyCcaBusyStart (Time duration);
-  void LogPreviousIdleAndCcaBusyStates (void);
-  void SwitchToTx (Time txDuration);
-  void SwitchToSync (Time syncDuration);
-  void SwitchFromSync (void);
-  void SwitchMaybeToCcaBusy (Time duration);
-  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);
-  double Log2 (double val) const;
-  double GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const;
-  double GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const;
-  uint32_t Factorial (uint32_t k) const;
-  double Binomial (uint32_t k, double p, uint32_t n) const;
-  double CalculatePdOdd (double ber, unsigned int d) const;
-  double CalculatePdEven (double ber, unsigned int d) const;
-  double CalculatePd (double ber, unsigned int d) const;
-  double GetFecBpskBer (double snr, double nbits, 
-                        uint32_t signalSpread, uint32_t phyRate,
-                        uint32_t dFree, uint32_t adFree) const;
-  double GetFecQamBer (double snr, uint32_t nbits, 
-                       uint32_t signalSpread,
-                       uint32_t phyRate,
-                       uint32_t m, uint32_t dfree,
-                       uint32_t adFree, uint32_t adFreePlusOne) const;
-  double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const;
-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_txGainDb;
-  double   m_rxGainDb;
-  double   m_rxNoiseRatio;
-  double   m_txPowerBaseDbm;
-  double   m_txPowerEndDbm;
-  uint32_t m_nTxPower;
-
-  
-  bool m_syncing;
-  Time m_endTx;
-  Time m_endSync;
-  Time m_endCcaBusy;
-  Time m_startTx;
-  Time m_startSync;
-  Time m_startCcaBusy;
-  Time m_previousStateChangeTime;
-
-  Ptr<WifiChannel> m_channel;
-  SyncOkCallback m_syncOkCallback;
-  SyncErrorCallback m_syncErrorCallback;
-  TracedCallback<Ptr<const Packet>, double, WifiMode, enum WifiPreamble> m_rxOkTrace;
-  TracedCallback<Ptr<const Packet>, double> m_rxErrorTrace;
-  TracedCallback<Ptr<const Packet>,WifiMode,WifiPreamble,uint8_t> m_txTrace;
-  Modes m_modes;
-  Listeners m_listeners;
-  EventId m_endSyncEvent;
-  Events m_events;
-  UniformVariable m_random;
-  TracedCallback<Time,Time,enum WifiPhy::State> m_stateLogger;
-  WifiPhyStandard m_standard;
+  static WifiMode g_6mba;
+  static WifiMode g_9mba;
+  static WifiMode g_12mba;
+  static WifiMode g_18mba;
+  static WifiMode g_24mba;
+  static WifiMode g_36mba;
+  static WifiMode g_48mba;
+  static WifiMode g_54mba;
 };
 
 } // namespace ns3
--- a/src/devices/wifi/wifi-test.cc	Wed Jun 11 11:15:43 2008 -0700
+++ b/src/devices/wifi/wifi-test.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -3,7 +3,7 @@
 #include "wifi-net-device.h"
 #include "wifi-channel.h"
 #include "adhoc-wifi-mac.h"
-#include "wifi-phy.h"
+#include "yans-wifi-phy.h"
 #include "arf-wifi-manager.h"
 #include "propagation-delay-model.h"
 #include "propagation-loss-model.h"
@@ -50,7 +50,7 @@
 
   Ptr<WifiMac> mac = m_mac.Create<WifiMac> ();
   Ptr<StaticMobilityModel> mobility = CreateObject<StaticMobilityModel> ();
-  Ptr<WifiPhy> phy = CreateObject<WifiPhy> ();
+  Ptr<WifiPhy> phy = CreateObject<YansWifiPhy> ();
   Ptr<WifiRemoteStationManager> manager = m_manager.Create<WifiRemoteStationManager> ();
 
   mobility->SetPosition (pos);
--- a/src/devices/wifi/wscript	Wed Jun 11 11:15:43 2008 -0700
+++ b/src/devices/wifi/wscript	Wed Jun 11 11:52:40 2008 -0700
@@ -11,6 +11,7 @@
         'wifi-mode.cc',
         'ssid.cc',
         'wifi-phy.cc',
+        'yans-wifi-phy.cc',
         'wifi-mac-header.cc',
         'wifi-mac-trailer.cc',
         'mac-low.cc',
@@ -53,6 +54,7 @@
         'ssid.h',
         'wifi-preamble.h',
 	'wifi-phy-standard.h',
+        'yans-wifi-phy.h',
         'wifi-phy.h',
         'wifi-remote-station-manager.h',
         'arf-wifi-manager.h',
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/yans-wifi-phy.cc	Wed Jun 11 11:52:40 2008 -0700
@@ -0,0 +1,1361 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "yans-wifi-phy.h"
+#include "wifi-mode.h"
+#include "wifi-channel.h"
+#include "wifi-preamble.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/random-variable.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+#include "ns3/enum.h"
+#include "ns3/trace-source-accessor.h"
+#include <math.h>
+
+NS_LOG_COMPONENT_DEFINE ("YansWifiPhy");
+
+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 
+YansWifiPhy::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::YansWifiPhy")
+    .SetParent<WifiPhy> ()
+    .AddConstructor<YansWifiPhy> ()
+    .AddAttribute ("EnergyDetectionThreshold",
+                   "The energy of a received signal should be higher than "
+                   "this threshold (dbm) to allow the PHY layer to detect the signal.",
+                   DoubleValue (-140.0),
+                   MakeDoubleAccessor (&YansWifiPhy::SetEdThreshold,
+                                       &YansWifiPhy::GetEdThreshold),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxGain",
+                   "Transmission gain (dB).",
+                   DoubleValue (1.0),
+                   MakeDoubleAccessor (&YansWifiPhy::SetTxGain,
+                                       &YansWifiPhy::GetTxGain),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxGain",
+                   "Reception gain (dB).",
+                   DoubleValue (1.0),
+                   MakeDoubleAccessor (&YansWifiPhy::SetRxGain,
+                                       &YansWifiPhy::GetRxGain),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerLevels",
+                   "Number of transmission power levels available between "
+                   "TxPowerBase and TxPowerEnd included.",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&YansWifiPhy::m_nTxPower),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("TxPowerEnd",
+                   "Maximum available transmission level (dbm).",
+                   DoubleValue (16.0206),
+                   MakeDoubleAccessor (&YansWifiPhy::SetTxPowerEnd, 
+                                       &YansWifiPhy::GetTxPowerEnd),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerStart",
+                   "Minimum available transmission level (dbm).",
+                   DoubleValue (16.0206),
+                   MakeDoubleAccessor (&YansWifiPhy::SetTxPowerStart, 
+                                       &YansWifiPhy::GetTxPowerStart),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxNoise",
+                   "Ratio of energy lost by receiver (dB).",
+                   DoubleValue (7),
+                   MakeDoubleAccessor (&YansWifiPhy::SetRxNoise,
+                                       &YansWifiPhy::GetRxNoise),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Standard", "The standard chosen configures a set of transmission modes"
+                   " and some PHY-specific constants.",
+                   EnumValue (WIFI_PHY_STANDARD_80211a),
+                   MakeEnumAccessor (&YansWifiPhy::SetStandard),
+                   MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a",
+                                    WIFI_PHY_STANDARD_holland, "holland"))
+    .AddTraceSource ("State",
+                     "The YansWifiPhy state",
+                     MakeTraceSourceAccessor (&YansWifiPhy::m_stateLogger))
+    .AddTraceSource ("RxOk",
+                     "A packet has been received successfully.",
+                     MakeTraceSourceAccessor (&YansWifiPhy::m_rxOkTrace))
+    .AddTraceSource ("RxError",
+                     "A packet has been received unsuccessfully.",
+                     MakeTraceSourceAccessor (&YansWifiPhy::m_rxErrorTrace))
+    .AddTraceSource ("Tx", "Packet transmission is starting.",
+                     MakeTraceSourceAccessor (&YansWifiPhy::m_txTrace))
+    ;
+  return tid;
+}
+
+YansWifiPhy::YansWifiPhy ()
+  : m_syncing (false),
+    m_endTx (Seconds (0)),
+    m_endSync (Seconds (0)),
+    m_endCcaBusy (Seconds (0)),
+    m_startTx (Seconds (0)),
+    m_startSync (Seconds (0)),
+    m_startCcaBusy (Seconds (0)),
+    m_previousStateChangeTime (Seconds (0)),
+    m_endSyncEvent (),
+    m_random (0.0, 1.0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+YansWifiPhy::~YansWifiPhy ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+YansWifiPhy::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_channel = 0;
+  m_events.clear ();
+  m_modes.clear ();
+}
+
+void
+YansWifiPhy::SetStandard (enum WifiPhyStandard standard)
+{
+  NS_LOG_FUNCTION (this << standard);
+  m_standard = standard;
+  switch (standard) {
+  case WIFI_PHY_STANDARD_80211a:
+    Configure80211a ();
+    break;
+  case WIFI_PHY_STANDARD_holland:
+    ConfigureHolland ();
+    break;
+  default:
+    NS_ASSERT (false);
+    break;
+  }
+}
+
+
+void 
+YansWifiPhy::SetRxNoise (double db)
+{
+  NS_LOG_FUNCTION (this << db);
+  m_rxNoiseRatio = DbToRatio (db);
+}
+void 
+YansWifiPhy::SetTxPowerStart (double start)
+{
+  NS_LOG_FUNCTION (this << start);
+  m_txPowerBaseDbm = start;
+}
+void 
+YansWifiPhy::SetTxPowerEnd (double end)
+{
+  NS_LOG_FUNCTION (this << end);
+  m_txPowerEndDbm = end;
+}
+void 
+YansWifiPhy::SetNTxPower (uint32_t n)
+{
+  NS_LOG_FUNCTION (this << n);
+  m_nTxPower = n;
+}
+void 
+YansWifiPhy::SetTxGain (double gain)
+{
+  NS_LOG_FUNCTION (this << gain);
+  m_txGainDb = gain;
+}
+void 
+YansWifiPhy::SetRxGain (double gain)
+{
+  NS_LOG_FUNCTION (this << gain);
+  m_rxGainDb = gain;
+}
+void 
+YansWifiPhy::SetEdThreshold (double threshold)
+{
+  NS_LOG_FUNCTION (this << threshold);
+  m_edThresholdW = DbmToW (threshold);
+}
+double 
+YansWifiPhy::GetRxNoise (void) const
+{
+  return RatioToDb (m_rxNoiseRatio);
+}
+double 
+YansWifiPhy::GetTxPowerStart (void) const
+{
+  return m_txPowerBaseDbm;
+}
+double 
+YansWifiPhy::GetTxPowerEnd (void) const
+{
+  return m_txPowerEndDbm;
+}
+double 
+YansWifiPhy::GetTxGain (void) const
+{
+  return m_txGainDb;
+}
+double 
+YansWifiPhy::GetRxGain (void) const
+{
+  return m_rxGainDb;
+}
+
+double 
+YansWifiPhy::GetEdThreshold (void) const
+{
+  return WToDbm (m_edThresholdW);
+}
+
+Ptr<WifiChannel> 
+YansWifiPhy::GetChannel (void) const
+{
+  return m_channel;
+}
+
+void 
+YansWifiPhy::SetChannel (Ptr<WifiChannel> channel)
+{
+  m_channel = channel;
+}
+
+void 
+YansWifiPhy::SetReceiveOkCallback (SyncOkCallback callback)
+{
+  m_syncOkCallback = callback;
+}
+void 
+YansWifiPhy::SetReceiveErrorCallback (SyncErrorCallback callback)
+{
+  m_syncErrorCallback = callback;
+}
+void 
+YansWifiPhy::StartReceivePacket (Ptr<Packet> packet, 
+                             double rxPowerDbm,
+                             WifiMode txMode,
+                             enum WifiPreamble preamble)
+{
+  NS_LOG_FUNCTION (this << packet << rxPowerDbm << txMode << preamble);
+  rxPowerDbm += m_rxGainDb;
+  double rxPowerW = DbmToW (rxPowerDbm);
+  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);
+
+  switch (GetState ()) {
+  case YansWifiPhy::SYNC:
+    NS_LOG_DEBUG ("drop packet because already in Sync (power="<<
+                  rxPowerW<<"W)");
+    if (endRx > m_endSync) 
+      {
+        goto maybeCcaBusy;
+      }
+    break;
+  case YansWifiPhy::TX:
+    NS_LOG_DEBUG ("drop packet because already in Tx (power="<<
+                  rxPowerW<<"W)");
+    if (endRx > m_endTx) 
+      {
+        goto maybeCcaBusy;
+      }
+    break;
+  case YansWifiPhy::CCA_BUSY:
+  case YansWifiPhy::IDLE:
+    if (rxPowerW > m_edThresholdW) 
+      {
+        NS_LOG_DEBUG ("sync (power="<<rxPowerW<<"W)");
+        // sync to signal
+        NotifySyncStart (rxDuration);
+        SwitchToSync (rxDuration);
+        NS_ASSERT (m_endSyncEvent.IsExpired ());
+        m_endSyncEvent = Simulator::Schedule (rxDuration, &YansWifiPhy::EndSync, this, 
+                                              packet,
+                                              event);
+      }
+    else 
+      {
+        NS_LOG_DEBUG ("drop packet because signal power too Small ("<<
+                      rxPowerW<<"<"<<m_edThresholdW<<")");
+        goto maybeCcaBusy;
+      }
+    break;
+  }
+
+  return;
+
+ maybeCcaBusy:
+
+  if (rxPowerW > m_edThresholdW) 
+    {
+      SwitchMaybeToCcaBusy (rxDuration);
+      NotifyCcaBusyStart (rxDuration);
+    } 
+  else 
+    {
+      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 ();
+          SwitchMaybeToCcaBusy (delta);
+          NotifyCcaBusyStart (delta);
+        }
+    }
+
+}
+void 
+YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower)
+{
+  NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txPower);
+  /* Transmission can happen if:
+   *  - we are syncing on a packet. It is the responsability of the
+   *    MAC layer to avoid doing this but the PHY does nothing to 
+   *    prevent it.
+   *  - we are idle
+   */
+  NS_ASSERT (!IsStateTx ());
+
+  m_txTrace (packet, txMode, preamble, txPower);
+  Time txDuration = CalculateTxDuration (packet->GetSize (), txMode, preamble);
+  NotifyTxStart (txDuration);
+  SwitchToTx (txDuration);
+  m_channel->Send (this, packet, GetPowerDbm (txPower) + m_txGainDb, txMode, preamble);
+}
+
+uint32_t 
+YansWifiPhy::GetNModes (void) const
+{
+  return m_modes.size ();
+}
+WifiMode 
+YansWifiPhy::GetMode (uint32_t mode) const
+{
+  return m_modes[mode];
+}
+uint32_t 
+YansWifiPhy::GetNTxPower (void) const
+{
+  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 - 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-GetChunkSuccessRate (mode,snr, 2000*8);
+      std::cout <<ber<< " ";
+    }
+    std::cout << std::endl;
+  }
+#endif
+}
+
+void
+YansWifiPhy::Configure80211a (void)
+{
+  NS_LOG_FUNCTION (this);
+  Configure80211aParameters ();
+  m_modes.push_back (g_6mba);
+  m_modes.push_back (g_9mba);
+  m_modes.push_back (g_12mba);
+  m_modes.push_back (g_18mba);
+  m_modes.push_back (g_24mba);
+  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_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 
+YansWifiPhy::RegisterListener (WifiPhyListener *listener)
+{
+  m_listeners.push_back (listener);
+}
+
+bool 
+YansWifiPhy::IsStateCcaBusy (void)
+{
+  return GetState () == CCA_BUSY;
+}
+
+bool 
+YansWifiPhy::IsStateIdle (void)
+{
+  return (GetState () == IDLE)?true:false;
+}
+bool 
+YansWifiPhy::IsStateBusy (void)
+{
+  return (GetState () != IDLE)?true:false;
+}
+bool 
+YansWifiPhy::IsStateSync (void)
+{
+  return (GetState () == SYNC)?true:false;
+}
+bool 
+YansWifiPhy::IsStateTx (void)
+{
+  return (GetState () == TX)?true:false;
+}
+
+Time
+YansWifiPhy::GetStateDuration (void)
+{
+  return Simulator::Now () - m_previousStateChangeTime;
+}
+Time
+YansWifiPhy::GetDelayUntilIdle (void)
+{
+  Time retval;
+
+  switch (GetState ()) {
+  case SYNC:
+    retval = m_endSync - Simulator::Now ();
+    break;
+  case TX:
+    retval = m_endTx - Simulator::Now ();
+    break;
+  case CCA_BUSY:
+    retval = m_endCcaBusy - Simulator::Now ();
+    break;
+  case IDLE:
+    retval = Seconds (0);
+    break;
+  default:
+    NS_ASSERT (false);
+    // NOTREACHED
+    retval = Seconds (0);
+    break;
+  }
+  retval = Max (retval, Seconds (0));
+  return retval;
+}
+
+Time 
+YansWifiPhy::GetLastRxStartTime (void) const
+{
+  return m_startSync;
+}
+
+
+Time
+YansWifiPhy::CalculateTxDuration (uint32_t size, WifiMode payloadMode, 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);
+}
+
+char const *
+YansWifiPhy::StateToString (enum State state)
+{
+  switch (state) {
+  case TX:
+    return "TX";
+    break;
+  case CCA_BUSY:
+    return "CCA_BUSY";
+    break;
+  case IDLE:
+    return "IDLE";
+    break;
+  case SYNC:
+    return "SYNC";
+    break;
+  default:
+    NS_ASSERT (false);
+    // quiet compiler
+    return "INVALID";
+    break;
+  }
+}
+enum YansWifiPhy::State 
+YansWifiPhy::GetState (void)
+{
+  if (m_endTx > Simulator::Now ()) 
+    {
+      return YansWifiPhy::TX;
+    } 
+  else if (m_syncing) 
+    {
+      return YansWifiPhy::SYNC;
+    } 
+  else if (m_endCcaBusy > Simulator::Now ()) 
+    {
+      return YansWifiPhy::CCA_BUSY;
+    } 
+  else 
+    {
+      return YansWifiPhy::IDLE;
+    }
+}
+
+double 
+YansWifiPhy::DbToRatio (double dB) const
+{
+  double ratio = pow(10.0,dB/10.0);
+  return ratio;
+}
+
+double 
+YansWifiPhy::DbmToW (double dBm) const
+{
+  double mW = pow(10.0,dBm/10.0);
+  return mW / 1000.0;
+}
+
+double
+YansWifiPhy::WToDbm (double w) const
+{
+  return 10.0 * log10(w * 1000.0);
+}
+
+double
+YansWifiPhy::RatioToDb (double ratio) const
+{
+  return 10.0 * log10(ratio);
+}
+
+double
+YansWifiPhy::GetEdThresholdW (void) const
+{
+  return m_edThresholdW;
+}
+
+Time
+YansWifiPhy::GetMaxPacketDuration (void) const
+{
+  return m_maxPacketDuration;
+}
+
+double 
+YansWifiPhy::GetPowerDbm (uint8_t power) const
+{
+  NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm);
+  NS_ASSERT (m_nTxPower > 0);
+  double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / m_nTxPower;
+  return dbm;
+}
+
+void 
+YansWifiPhy::NotifyTxStart (Time duration)
+{
+  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
+    (*i)->NotifyTxStart (duration);
+  }
+}
+void 
+YansWifiPhy::NotifySyncStart (Time duration)
+{
+  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
+    (*i)->NotifyRxStart (duration);
+  }
+}
+void 
+YansWifiPhy::NotifySyncEndOk (void)
+{
+  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
+    (*i)->NotifyRxEndOk ();
+  }
+}
+void 
+YansWifiPhy::NotifySyncEndError (void)
+{
+  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
+    (*i)->NotifyRxEndError ();
+  }
+}
+void 
+YansWifiPhy::NotifyCcaBusyStart (Time duration)
+{
+  for (Listeners::const_iterator i = m_listeners.begin (); i != m_listeners.end (); i++) {
+    (*i)->NotifyCcaBusyStart (duration);
+  }
+}
+
+void
+YansWifiPhy::LogPreviousIdleAndCcaBusyStates (void)
+{
+  Time now = Simulator::Now ();
+  Time idleStart = Max (m_endCcaBusy, m_endSync);
+  idleStart = Max (idleStart, m_endTx);
+  NS_ASSERT (idleStart <= now);
+  if (m_endCcaBusy > m_endSync && 
+      m_endCcaBusy > m_endTx) {
+    Time ccaBusyStart = Max (m_endTx, m_endSync);
+    ccaBusyStart = Max (ccaBusyStart, m_startCcaBusy);
+    m_stateLogger (ccaBusyStart, idleStart - ccaBusyStart, YansWifiPhy::CCA_BUSY);
+  }
+  m_stateLogger (idleStart, now - idleStart, YansWifiPhy::IDLE);
+}
+
+void
+YansWifiPhy::SwitchToTx (Time txDuration)
+{
+  Time now = Simulator::Now ();
+  switch (GetState ()) {
+  case YansWifiPhy::SYNC:
+    /* The packet which is being received as well
+     * as its endSync event are cancelled by the caller.
+     */
+    m_syncing = false;
+    m_stateLogger (m_startSync, now - m_startSync, YansWifiPhy::SYNC);
+    m_endSyncEvent.Cancel ();
+    m_endSync = now;
+    break;
+  case YansWifiPhy::CCA_BUSY: {
+    Time ccaStart = Max (m_endSync, m_endTx);
+    ccaStart = Max (ccaStart, m_startCcaBusy);
+    m_stateLogger (ccaStart, now - ccaStart, YansWifiPhy::CCA_BUSY);
+  } break;
+  case YansWifiPhy::IDLE:
+    LogPreviousIdleAndCcaBusyStates ();
+    break;
+  default:
+    NS_ASSERT (false);
+    break;
+  }
+  m_stateLogger (now, txDuration, YansWifiPhy::TX);
+  m_previousStateChangeTime = now;
+  m_endTx = now + txDuration;
+  m_startTx = now;
+}
+void
+YansWifiPhy::SwitchToSync (Time rxDuration)
+{
+  NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
+  NS_ASSERT (!m_syncing);
+  Time now = Simulator::Now ();
+  switch (GetState ()) {
+  case YansWifiPhy::IDLE:
+    LogPreviousIdleAndCcaBusyStates ();
+    break;
+  case YansWifiPhy::CCA_BUSY: {
+    Time ccaStart = Max (m_endSync, m_endTx);
+    ccaStart = Max (ccaStart, m_startCcaBusy);
+    m_stateLogger (ccaStart, now - ccaStart, YansWifiPhy::CCA_BUSY);
+  } break;
+  case YansWifiPhy::SYNC:
+  case YansWifiPhy::TX:
+    NS_ASSERT (false);
+    break;
+  }
+  m_previousStateChangeTime = now;
+  m_syncing = true;
+  m_startSync = now;
+  m_endSync = now + rxDuration;
+  NS_ASSERT (IsStateSync ());
+}
+void
+YansWifiPhy::SwitchFromSync (void)
+{
+  NS_ASSERT (IsStateSync ());
+  NS_ASSERT (m_syncing);
+
+  Time now = Simulator::Now ();
+  m_stateLogger (m_startSync, now - m_startSync, YansWifiPhy::SYNC);
+  m_previousStateChangeTime = now;
+  m_syncing = false;
+
+  NS_ASSERT (IsStateIdle () || IsStateCcaBusy ());
+}
+void
+YansWifiPhy::SwitchMaybeToCcaBusy (Time duration)
+{
+  Time now = Simulator::Now ();
+  switch (GetState ()) {
+  case YansWifiPhy::IDLE:
+    LogPreviousIdleAndCcaBusyStates ();
+  break;
+  case YansWifiPhy::CCA_BUSY:
+    break;
+  case YansWifiPhy::SYNC:
+    break;
+  case YansWifiPhy::TX:
+    break;
+  }
+  m_startCcaBusy = now;
+  m_endCcaBusy = Max (m_endCcaBusy, now + duration);
+}
+
+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);
+}
+
+
+
+/**
+ * Stuff specific to the BER model here.
+ */
+double 
+YansWifiPhy::Log2 (double val) const
+{
+  return log(val) / log(2.0);
+}
+double 
+YansWifiPhy::GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const
+{
+  double EbNo = snr * signalSpread / phyRate;
+  double z = sqrt(EbNo);
+  double ber = 0.5 * erfc(z);
+  NS_LOG_INFO ("bpsk snr="<<snr<<" ber="<<ber);
+  return ber;
+}
+double 
+YansWifiPhy::GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const
+{
+  double EbNo = snr * signalSpread / phyRate;
+  double z = sqrt ((1.5 * Log2 (m) * EbNo) / (m - 1.0));
+  double z1 = ((1.0 - 1.0 / sqrt (m)) * erfc (z)) ;
+  double z2 = 1 - pow ((1-z1), 2.0);
+  double ber = z2 / Log2 (m);
+  NS_LOG_INFO ("Qam m="<<m<<" rate=" << phyRate << " snr="<<snr<<" ber="<<ber);
+  return ber;
+}
+uint32_t
+YansWifiPhy::Factorial (uint32_t k) const
+{
+  uint32_t fact = 1;
+  while (k > 0) 
+    {
+      fact *= k;
+      k--;
+    }
+  return fact;
+}
+double 
+YansWifiPhy::Binomial (uint32_t k, double p, uint32_t n) const
+{
+  double retval = Factorial (n) / (Factorial (k) * Factorial (n-k)) * pow (p, k) * pow (1-p, n-k);
+  return retval;
+}
+double 
+YansWifiPhy::CalculatePdOdd (double ber, unsigned int d) const
+{
+  NS_ASSERT ((d % 2) == 1);
+  unsigned int dstart = (d + 1) / 2;
+  unsigned int dend = d;
+  double pd = 0;
+
+  for (unsigned int i = dstart; i < dend; i++) 
+    {
+      pd += Binomial (i, ber, d);
+    }
+  return pd;
+}
+double 
+YansWifiPhy::CalculatePdEven (double ber, unsigned int d) const
+{
+  NS_ASSERT ((d % 2) == 0);
+  unsigned int dstart = d / 2 + 1;
+  unsigned int dend = d;
+  double pd = 0;
+
+  for (unsigned int i = dstart; i < dend; i++)
+    {
+      pd +=  Binomial (i, ber, d);
+    }
+  pd += 0.5 * Binomial (d / 2, ber, d);
+
+  return pd;
+}
+
+double 
+YansWifiPhy::CalculatePd (double ber, unsigned int d) const
+{
+  double pd;
+  if ((d % 2) == 0) 
+    {
+      pd = CalculatePdEven (ber, d);
+    } 
+  else 
+    {
+      pd = CalculatePdOdd (ber, d);
+    }
+  return pd;
+}
+
+double
+YansWifiPhy::GetFecBpskBer (double snr, double nbits, 
+                         uint32_t signalSpread, uint32_t phyRate,
+                         uint32_t dFree, uint32_t adFree) const
+{
+  double ber = GetBpskBer (snr, signalSpread, phyRate);
+  if (ber == 0.0) 
+    {
+      return 1.0;
+    }
+  double pd = CalculatePd (ber, dFree);
+  double pmu = adFree * pd;
+  pmu = std::min (pmu, 1.0);
+  double pms = pow (1 - pmu, nbits);
+  return pms;
+}
+
+double
+YansWifiPhy::GetFecQamBer (double snr, uint32_t nbits, 
+                       uint32_t signalSpread,
+                       uint32_t phyRate,
+                       uint32_t m, uint32_t dFree,
+                       uint32_t adFree, uint32_t adFreePlusOne) const
+{
+  double ber = GetQamBer (snr, m, signalSpread, phyRate);
+  if (ber == 0.0) 
+    {
+      return 1.0;
+    }
+  /* first term */
+  double pd = CalculatePd (ber, dFree);
+  double pmu = adFree * pd;
+  /* second term */
+  pd = CalculatePd (ber, dFree + 1);
+  pmu += adFreePlusOne * pd;
+  pmu = std::min (pmu, 1.0);
+  double pms = pow (1 - pmu, nbits);
+  return pms;
+}
+
+double 
+YansWifiPhy::GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const
+{
+  if (mode.GetUid () == g_6mba.GetUid ())
+    {
+      return GetFecBpskBer (snr, 
+                            nbits,
+                            mode.GetBandwidth (), // signal spread
+                            mode.GetPhyRate (), // phy rate
+                            10, // dFree
+                            11 // adFree
+                            );      
+    }
+  else if (mode.GetUid () == g_9mba.GetUid ())
+    {
+      return GetFecBpskBer (snr, 
+                            nbits,
+                            mode.GetBandwidth (), // signal spread
+                            mode.GetPhyRate (), // phy rate
+                            5, // dFree
+                            8 // adFree
+                            );
+    }
+  else if (mode.GetUid () == g_12mba.GetUid ())
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           4,  // m 
+                           10, // dFree
+                           11, // adFree
+                           0   // adFreePlusOne
+                           );
+    }
+  else if (mode.GetUid () == g_18mba.GetUid ())
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           4, // m
+                           5, // dFree
+                           8, // adFree
+                           31 // adFreePlusOne
+                           );
+    }
+  else if (mode.GetUid () == g_24mba.GetUid ())
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           16, // m
+                           10, // dFree
+                           11, // adFree
+                           0   // adFreePlusOne
+                           );
+    }
+  else if (mode.GetUid () == g_36mba.GetUid ())
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           16, // m
+                           5,  // dFree
+                           8,  // adFree
+                           31  // adFreePlusOne
+                           );
+    }
+  else if (mode.GetUid () == g_48mba.GetUid ())
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           64, // m
+                           6,  // dFree
+                           1,  // adFree
+                           16  // adFreePlusOne
+                           );
+    }
+  else if (mode.GetUid () == g_54mba.GetUid ())
+    {
+      return GetFecQamBer (snr, 
+                           nbits,
+                           mode.GetBandwidth (), // signal spread
+                           mode.GetPhyRate (), // phy rate
+                           64, // m
+                           5,  // dFree
+                           8,  // adFree
+                           31  // adFreePlusOne
+                           );
+    }
+  return 0;
+}
+
+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 = 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)
+{
+  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 ());
+  
+  /* 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-GetChunkSuccessRate (event->GetPayloadMode (), snr, 1))<<
+                ", snr="<<snr<<", per="<<per<<", size="<<packet->GetSize ());
+  
+  if (m_random.GetValue () > per) 
+    {
+      NotifySyncEndOk ();
+      SwitchFromSync ();
+      m_rxOkTrace (packet, snr, event->GetPayloadMode (), event->GetPreambleType ());
+      if (!m_syncOkCallback.IsNull ())
+        {
+          m_syncOkCallback (packet, snr, event->GetPayloadMode (), event->GetPreambleType ());
+        }
+    } 
+  else 
+    {
+      /* failure. */
+      NotifySyncEndError ();
+      SwitchFromSync ();
+      m_rxErrorTrace (packet, snr);
+      if (!m_syncErrorCallback.IsNull ())
+        {
+          m_syncErrorCallback (packet, snr);
+        }
+    }
+}
+
+
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/yans-wifi-phy.h	Wed Jun 11 11:52:40 2008 -0700
@@ -0,0 +1,222 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#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"
+#include "ns3/packet.h"
+#include "ns3/object.h"
+#include "ns3/traced-callback.h"
+#include "ns3/nstime.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "wifi-phy.h"
+#include "wifi-mode.h"
+#include "wifi-preamble.h"
+#include "wifi-phy-standard.h"
+
+
+namespace ns3 {
+
+class RandomUniform;
+class RxEvent;
+class WifiChannel;
+
+
+/**
+ * \brief 802.11 PHY layer model
+ *
+ * This PHY implements a model of 802.11a. The model
+ * implemented here is based on the model described
+ * in "Yet Another Network Simulator", 
+ * (http://cutebugs.net/files/wns2-yans.pdf).
+ *
+ *
+ * This PHY model depends on a channel loss and delay
+ * model as provided by the ns3::PropagationLossModel
+ * and ns3::PropagationDelayModel classes, both of which are
+ * members of the ns3::WifiChannel class.
+ */
+class YansWifiPhy : public WifiPhy
+{
+public:
+
+  static TypeId GetTypeId (void);
+
+  YansWifiPhy ();
+  virtual ~YansWifiPhy ();
+
+  void SetStandard (enum WifiPhyStandard standard);
+  void SetRxNoise (double ratio);
+  void SetTxPowerStart (double start);
+  void SetTxPowerEnd (double end);
+  void SetNTxPower (uint32_t n);
+  void SetTxGain (double gain);
+  void SetRxGain (double gain);
+  void SetEdThreshold (double threshold);
+  double GetRxNoise (void) const;
+  double GetTxGain (void) const;
+  double GetRxGain (void) const;
+  double GetEdThreshold (void) const;
+
+
+  virtual double GetTxPowerStart (void) const;
+  virtual double GetTxPowerEnd (void) const;
+  virtual uint32_t GetNTxPower (void) const;
+  virtual void SetChannel (Ptr<WifiChannel> channel);
+  virtual void SetReceiveOkCallback (WifiPhy::SyncOkCallback callback);
+  virtual void SetReceiveErrorCallback (WifiPhy::SyncErrorCallback callback);
+  virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel);
+  virtual void RegisterListener (WifiPhyListener *listener);
+  virtual bool IsStateCcaBusy (void);
+  virtual bool IsStateIdle (void);
+  virtual bool IsStateBusy (void);
+  virtual bool IsStateSync (void);
+  virtual bool IsStateTx (void);
+  virtual Time GetStateDuration (void);
+  virtual Time GetDelayUntilIdle (void);
+  virtual Time GetLastRxStartTime (void) const;
+  virtual Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const;
+  virtual uint32_t GetNModes (void) const;
+  virtual WifiMode GetMode (uint32_t mode) const;
+  virtual double CalculateSnr (WifiMode txMode, double ber) const;
+  virtual void StartReceivePacket (Ptr<Packet> packet,
+                                   double rxPowerDbm,
+                                   WifiMode mode,
+                                   WifiPreamble preamble);
+  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<WifiPhyListener *> Listeners;
+  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);
+  char const *StateToString (enum State state);
+  enum YansWifiPhy::State GetState (void);
+  double GetEdThresholdW (void) const;
+  double DbmToW (double dbm) const;
+  double DbToRatio (double db) const;
+  double WToDbm (double w) const;
+  double RatioToDb (double ratio) const;
+  Time GetMaxPacketDuration (void) const;
+  void CancelRx (void);
+  double GetPowerDbm (uint8_t power) const;
+  void NotifyTxStart (Time duration);
+  void NotifyWakeup (void);
+  void NotifySyncStart (Time duration);
+  void NotifySyncEndOk (void);
+  void NotifySyncEndError (void);
+  void NotifyCcaBusyStart (Time duration);
+  void LogPreviousIdleAndCcaBusyStates (void);
+  void SwitchToTx (Time txDuration);
+  void SwitchToSync (Time syncDuration);
+  void SwitchFromSync (void);
+  void SwitchMaybeToCcaBusy (Time duration);
+  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);
+  double Log2 (double val) const;
+  double GetBpskBer (double snr, uint32_t signalSpread, uint32_t phyRate) const;
+  double GetQamBer (double snr, unsigned int m, uint32_t signalSpread, uint32_t phyRate) const;
+  uint32_t Factorial (uint32_t k) const;
+  double Binomial (uint32_t k, double p, uint32_t n) const;
+  double CalculatePdOdd (double ber, unsigned int d) const;
+  double CalculatePdEven (double ber, unsigned int d) const;
+  double CalculatePd (double ber, unsigned int d) const;
+  double GetFecBpskBer (double snr, double nbits, 
+                        uint32_t signalSpread, uint32_t phyRate,
+                        uint32_t dFree, uint32_t adFree) const;
+  double GetFecQamBer (double snr, uint32_t nbits, 
+                       uint32_t signalSpread,
+                       uint32_t phyRate,
+                       uint32_t m, uint32_t dfree,
+                       uint32_t adFree, uint32_t adFreePlusOne) const;
+  double GetChunkSuccessRate (WifiMode mode, double snr, uint32_t nbits) const;
+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_txGainDb;
+  double   m_rxGainDb;
+  double   m_rxNoiseRatio;
+  double   m_txPowerBaseDbm;
+  double   m_txPowerEndDbm;
+  uint32_t m_nTxPower;
+
+  
+  bool m_syncing;
+  Time m_endTx;
+  Time m_endSync;
+  Time m_endCcaBusy;
+  Time m_startTx;
+  Time m_startSync;
+  Time m_startCcaBusy;
+  Time m_previousStateChangeTime;
+
+  Ptr<WifiChannel> m_channel;
+  SyncOkCallback m_syncOkCallback;
+  SyncErrorCallback m_syncErrorCallback;
+  TracedCallback<Ptr<const Packet>, double, WifiMode, enum WifiPreamble> m_rxOkTrace;
+  TracedCallback<Ptr<const Packet>, double> m_rxErrorTrace;
+  TracedCallback<Ptr<const Packet>,WifiMode,WifiPreamble,uint8_t> m_txTrace;
+  Modes m_modes;
+  Listeners m_listeners;
+  EventId m_endSyncEvent;
+  Events m_events;
+  UniformVariable m_random;
+  TracedCallback<Time,Time,enum YansWifiPhy::State> m_stateLogger;
+  WifiPhyStandard m_standard;
+};
+
+} // namespace ns3
+
+
+#endif /* YANS_WIFI_PHY_H */