Port spectrum PHY changes to Wi-Fi model
authorDean Armstrong <deanarm@gmail.com>
Tue, 15 Feb 2011 16:00:42 +0000
changeset 6818 6b56326402a8
parent 6817 3c98f50788d5
child 6819 69fa08fe3ecb
Port spectrum PHY changes to Wi-Fi model
src/devices/wifi/interference-helper.cc
src/devices/wifi/mac-low.cc
src/devices/wifi/mac-low.h
src/devices/wifi/spectrum-yans-wifi-phy.cc
src/devices/wifi/spectrum-yans-wifi-phy.h
src/devices/wifi/wifi-mode.h
src/devices/wifi/wifi-phy-tag.cc
src/devices/wifi/wifi-phy-tag.h
src/devices/wifi/wifi-phy.h
src/devices/wifi/wifi-spectrum-error-model.cc
src/devices/wifi/wifi-spectrum-error-model.h
src/devices/wifi/wifi-spectrum-phy-interface.cc
src/devices/wifi/wifi-spectrum-phy-interface.h
src/devices/wifi/wifi-spectrum-value-helper.cc
src/devices/wifi/wifi-spectrum-value-helper.h
src/devices/wifi/wscript
src/devices/wifi/yans-wifi-phy.cc
src/devices/wifi/yans-wifi-phy.h
src/helper/spectrum-wifi-helper.cc
src/helper/spectrum-wifi-helper.h
src/helper/wifi-helper.cc
src/helper/wscript
src/spectrum/model/wifi-spectrum-value-helper.cc
src/spectrum/model/wifi-spectrum-value-helper.h
src/spectrum/wscript
--- a/src/devices/wifi/interference-helper.cc	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/interference-helper.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -226,7 +226,6 @@
 InterferenceHelper::CalculateNoiseInterferenceW (Ptr<InterferenceHelper::Event> event, NiChanges *ni) const
 {
   double noiseInterference = m_firstPower;
-  NS_ASSERT (m_rxing);
   for (NiChanges::const_iterator i = m_niChanges.begin () + 1; i != m_niChanges.end (); i++)
     {
       if ((event->GetEndTime () == i->GetTime ()) && event->GetRxPowerW () == -i->GetDelta ())
--- a/src/devices/wifi/mac-low.cc	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/mac-low.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -1140,7 +1140,7 @@
 }
 
 void
-MacLow::ForwardDown (Ptr<const Packet> packet, const WifiMacHeader* hdr, 
+MacLow::ForwardDown (Ptr<Packet> packet, const WifiMacHeader* hdr,
                      WifiMode txMode)
 {
   NS_LOG_FUNCTION (this << packet << hdr << txMode);
--- a/src/devices/wifi/mac-low.h	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/mac-low.h	Tue Feb 15 16:00:42 2011 +0000
@@ -495,7 +495,7 @@
   uint32_t GetCtsSize (void) const;
   uint32_t GetSize (Ptr<const Packet> packet, const WifiMacHeader *hdr) const;
   Time NowUs (void) const;
-  void ForwardDown (Ptr<const Packet> packet, const WifiMacHeader *hdr, 
+  void ForwardDown (Ptr<Packet> packet, const WifiMacHeader *hdr,
                     WifiMode txMode);
   Time CalculateOverallTxTime (Ptr<const Packet> packet,
                                const WifiMacHeader* hdr, 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/spectrum-yans-wifi-phy.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,810 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * Copyright (c) 2009 CTTC
+ *
+ * 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
+ *
+ * Original Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Ported to the Spectrum framework by Nicola Baldo <nbaldo@cttc.es> on June 2009
+ */
+
+#include <ns3/spectrum-channel.h>
+#include "wifi-channel.h"
+#include "spectrum-yans-wifi-phy.h"
+#include "wifi-mode.h"
+#include "wifi-preamble.h"
+#include "wifi-phy-tag.h"
+#include "wifi-phy-state-helper.h"
+#include "error-rate-model.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/packet-burst.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/pointer.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/spectrum-value.h"
+#include <float.h>
+#include "ns3/wifi-net-device.h"
+
+#include "wifi-spectrum-error-model.h"
+#include "ns3/spectrum-model-ism2400MHz-res1MHz.h"
+
+NS_LOG_COMPONENT_DEFINE ("SpectrumYansWifiPhy");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (SpectrumYansWifiPhy);
+
+TypeId
+SpectrumYansWifiPhy::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SpectrumYansWifiPhy")
+    .SetParent<WifiPhy> ()
+    .AddConstructor<SpectrumYansWifiPhy> ()
+    .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 (&SpectrumYansWifiPhy::SetEdThreshold,
+                                       &SpectrumYansWifiPhy::GetEdThreshold),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("CcaMode1Threshold",
+                   "The energy of a received signal should be higher than "
+                   "this threshold (dBm) to allow the PHY layer to declare "
+                   "CCA BUSY state. The default value is set roughly in line "
+                   "with the various diktats in the standard.",
+                   DoubleValue (-80.0),
+                   MakeDoubleAccessor (&SpectrumYansWifiPhy::SetCcaMode1Threshold,
+                                       &SpectrumYansWifiPhy::GetCcaMode1Threshold),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerLevels",
+                   "Number of transmission power levels available between "
+                   "TxPowerBase and TxPowerEnd included.",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&SpectrumYansWifiPhy::m_nTxPower),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("TxPowerEnd",
+                   "Maximum available transmission level (dbm).",
+                   DoubleValue (16.0206),
+                   MakeDoubleAccessor (&SpectrumYansWifiPhy::SetTxPowerEnd,
+                                       &SpectrumYansWifiPhy::GetTxPowerEnd),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TxPowerStart",
+                   "Minimum available transmission level (dbm).",
+                   DoubleValue (16.0206),
+                   MakeDoubleAccessor (&SpectrumYansWifiPhy::SetTxPowerStart,
+                                       &SpectrumYansWifiPhy::GetTxPowerStart),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RxNoiseFigure",
+                   "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
+                   " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
+                   "\"the difference in decibels (dB) between"
+                   " the noise output of the actual receiver to the noise output of an "
+                   " ideal receiver with the same overall gain and bandwidth when the receivers "
+                   " are connected to sources at the standard noise temperature T0 (usually 290 K)\"."
+                   " For",
+                   DoubleValue (7),
+                   MakeDoubleAccessor (&SpectrumYansWifiPhy::SetRxNoiseFigure,
+                                       &SpectrumYansWifiPhy::GetRxNoiseFigure),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("State", "The state of the PHY layer",
+                   PointerValue (),
+                   MakePointerAccessor (&SpectrumYansWifiPhy::m_state),
+                   MakePointerChecker<WifiPhyStateHelper> ())
+    ;
+  return tid;
+}
+
+SpectrumYansWifiPhy::SpectrumYansWifiPhy ()
+  :  m_channelFreqMhz(2437),
+     m_channelNumber(1),
+     m_endRxEvent (),
+     m_random (0.0, 1.0),
+     m_spectrumValueHelper (0)
+{
+  NS_LOG_FUNCTION (this);
+  m_state = CreateObject<WifiPhyStateHelper> ();
+
+  // Create the object that tracks all energy in our receive spectrum.
+  m_spectrumInterferenceTracker =
+    CreateObject<SpectrumInterference> ();
+  m_errorModel = CreateObject<WifiSpectrumErrorModel> ();
+  m_spectrumInterferenceTracker->SetErrorModel (m_errorModel);
+}
+
+void
+SpectrumYansWifiPhy::CreateWifiSpectrumPhyInterface (Ptr<Node> node, Ptr<WifiNetDevice> device)
+{
+  m_wifiSpectrumPhyInterface = CreateObject<WifiSpectrumPhyInterface> ();
+  m_wifiSpectrumPhyInterface->SetSpectrumYansWifiPhy(this);
+  m_wifiSpectrumPhyInterface->SetMobility(node);
+  m_wifiSpectrumPhyInterface->SetDevice(device);
+}
+
+SpectrumYansWifiPhy::~SpectrumYansWifiPhy ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+SpectrumYansWifiPhy::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_channel = 0;
+  m_deviceRateSet.clear ();
+  m_device = 0;
+}
+
+SpectrumType
+SpectrumYansWifiPhy::GetSpectrumType ()
+{
+  NS_LOG_FUNCTION (this);
+  static SpectrumType st = SpectrumTypeFactory::Create ("IdealOfdm");
+  return st;
+}
+
+
+void
+SpectrumYansWifiPhy::ConfigureStandard (enum WifiPhyStandard standard)
+{
+  NS_LOG_FUNCTION (this << standard);
+  m_standard = standard;
+  switch (standard) {
+  case WIFI_PHY_STANDARD_80211a:
+    Configure80211a ();
+    break;
+  case WIFI_PHY_STANDARD_80211b:
+    Configure80211b ();
+    break;
+  case WIFI_PHY_STANDARD_80211g:
+    Configure80211g ();
+    break;
+  case WIFI_PHY_STANDARD_holland:
+    ConfigureHolland ();
+    break;
+  default:
+    NS_ASSERT (false);
+    break;
+  }
+}
+
+
+void
+SpectrumYansWifiPhy::SetRxNoiseFigure (double noiseFigureDb)
+{
+  NS_LOG_FUNCTION (this << noiseFigureDb);
+  m_interference.SetNoiseFigure (DbToRatio (noiseFigureDb));
+}
+void
+SpectrumYansWifiPhy::SetTxPowerStart (double start)
+{
+  NS_LOG_FUNCTION (this << start);
+  m_txPowerBaseDbm = start;
+}
+void
+SpectrumYansWifiPhy::SetTxPowerEnd (double end)
+{
+  NS_LOG_FUNCTION (this << end);
+  m_txPowerEndDbm = end;
+}
+void
+SpectrumYansWifiPhy::SetNTxPower (uint32_t n)
+{
+  NS_LOG_FUNCTION (this << n);
+  m_nTxPower = n;
+}
+void
+SpectrumYansWifiPhy::SetSpectrumValueHelper (Ptr<WifiSpectrumValueHelper> helper)
+{
+  m_spectrumValueHelper = helper;
+  Ptr<SpectrumValue> noisePsd = Create <SpectrumValue> (GetRxSpectrumModel ());
+  *noisePsd = 1.381e-23/* Joules/Kelvin */ * 300/* Kelvin */;
+  m_spectrumInterferenceTracker->SetNoisePowerSpectralDensity (noisePsd);
+}
+void
+SpectrumYansWifiPhy::SetEdThreshold (double threshold)
+{
+  NS_LOG_FUNCTION (this << threshold);
+  m_edThresholdW = DbmToW (threshold);
+}
+void
+SpectrumYansWifiPhy::SetCcaMode1Threshold (double threshold)
+{
+  NS_LOG_FUNCTION (this << threshold);
+  m_ccaMode1ThresholdW = DbmToW (threshold);
+}
+void
+SpectrumYansWifiPhy::SetErrorRateModel (Ptr<ErrorRateModel> rate)
+{
+  m_interference.SetErrorRateModel (rate);
+}
+void
+SpectrumYansWifiPhy::SetDevice (Ptr<Object> device)
+{
+  m_device = device;
+}
+void
+SpectrumYansWifiPhy::SetMobility (Ptr<Object> mobility)
+{
+  m_mobility = mobility;
+}
+
+double
+SpectrumYansWifiPhy::GetRxNoiseFigure (void) const
+{
+  return RatioToDb (m_interference.GetNoiseFigure ());
+}
+double
+SpectrumYansWifiPhy::GetTxPowerStart (void) const
+{
+  return m_txPowerBaseDbm;
+}
+double
+SpectrumYansWifiPhy::GetTxPowerEnd (void) const
+{
+  return m_txPowerEndDbm;
+}
+
+double
+SpectrumYansWifiPhy::GetEdThreshold (void) const
+{
+  return WToDbm (m_edThresholdW);
+}
+
+double
+SpectrumYansWifiPhy::GetCcaMode1Threshold (void) const
+{
+  return WToDbm (m_ccaMode1ThresholdW);
+}
+
+Ptr<ErrorRateModel>
+SpectrumYansWifiPhy::GetErrorRateModel (void) const
+{
+  return m_interference.GetErrorRateModel ();
+}
+Ptr<Object>
+SpectrumYansWifiPhy::GetDevice (void) const
+{
+  return m_device;
+}
+Ptr<Object>
+SpectrumYansWifiPhy::GetMobility (void)
+{
+  return m_mobility;
+}
+
+Ptr<SpectrumPhy>
+SpectrumYansWifiPhy::GetSpectrumPhy (void)
+{
+  return (m_wifiSpectrumPhyInterface->GetObject<SpectrumPhy> ());
+}
+
+void
+SpectrumYansWifiPhy::SetSpectrumPhy (Ptr<WifiSpectrumPhyInterface> wifiSpectrumPhyInterface)
+{
+  m_wifiSpectrumPhyInterface = wifiSpectrumPhyInterface;
+}
+
+
+double
+SpectrumYansWifiPhy::CalculateSnr (WifiMode txMode, double ber) const
+{
+  return m_interference.GetErrorRateModel ()->CalculateSnr (txMode, ber);
+}
+
+Ptr<WifiChannel>
+SpectrumYansWifiPhy::GetChannel (void) const
+{
+  return Ptr<WifiChannel>(0);
+}
+void
+SpectrumYansWifiPhy::SetChannel (Ptr<SpectrumChannel> channel)
+{
+  m_channel = channel;
+}
+
+void
+SpectrumYansWifiPhy::SetReceiveOkCallback (RxOkCallback callback)
+{
+  m_state->SetReceiveOkCallback (callback);
+}
+void
+SpectrumYansWifiPhy::SetReceiveErrorCallback (RxErrorCallback callback)
+{
+  m_state->SetReceiveErrorCallback (callback);
+}
+
+void
+SpectrumYansWifiPhy:: StartRx(Ptr<PacketBurst> burst,
+                              Ptr <const SpectrumValue> rxPowerSpectrum,
+                              SpectrumType st,
+                              Time rxDuration)
+{
+  NS_LOG_FUNCTION (this);
+
+  // Track signals that hit our antenna, regardless of radio state.
+  m_spectrumInterferenceTracker->AddSignal (rxPowerSpectrum, rxDuration);
+
+  // HERE: We currently ignore any burst that is not a Wi-Fi
+  // burst. This method really needs to be reworked to handle the
+  // interference properly.
+  if (st != GetSpectrumType ())
+    {
+      NS_LOG_INFO ("Received non Wi-Fi signal");
+      return;
+    }
+
+  std::list<Ptr<Packet> > packets = burst->GetPackets ();
+  for (std::list<Ptr<Packet> >::iterator iter = packets.begin (); iter != packets.end (); ++iter)
+  {
+    Ptr<Packet> packet = *iter;
+
+    WifiPhyTag tag;
+    packet->PeekPacketTag(tag);
+    WifiMode txMode = tag.GetWifiMode ();
+    enum WifiPreamble preamble = tag.GetWifiPreamble ();
+
+    // Integrate over our receive bandwidth (i.e., all that the receive
+    // spectral mask representing our filtering allows) to find the
+    // total energy apparent to the "demodulator".
+    double rxPowerW = Sum ((*rxPowerSpectrum) *
+                           (*m_spectrumValueHelper->CreateRfFilter (m_channelNumber)));
+
+    Time endRx = Simulator::Now () + rxDuration;
+
+    Ptr<InterferenceHelper::Event> event;
+    event = m_interference.Add (packet->GetSize (),
+                                txMode,
+                                preamble,
+                                rxDuration,
+                                rxPowerW);
+
+    switch (m_state->GetState ()) {
+    case SpectrumYansWifiPhy::TX:
+      NS_LOG_DEBUG ("drop packet because already in Tx (power="<<
+                    rxPowerW<<"W)");
+      NotifyRxDrop (packet);
+      if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
+        {
+          // that packet will be noise _after_ the transmission of the
+          // currently-transmitted packet.
+          goto maybeCcaBusy;
+        }
+      break;
+    case SpectrumYansWifiPhy::CCA_BUSY:
+    case SpectrumYansWifiPhy::IDLE:
+      if (rxPowerW > m_edThresholdW)
+        {
+          // Indicate to our interference tracker that we are going to
+          // receive this one.
+          m_spectrumInterferenceTracker->StartRx (packet, rxPowerSpectrum);
+          m_errorModel->SetRxMask (CreateRxMask());
+
+          // sync to signal
+          m_state->SwitchToRx (rxDuration);
+          NS_ASSERT (m_endRxEvent.IsExpired ());
+          NotifyRxBegin (packet);
+          m_endRxEvent = Simulator::Schedule (rxDuration,
+                                                &SpectrumYansWifiPhy::EndRx, this,
+                                                packet,
+                                                event);
+        }
+      else
+        {
+          NS_LOG_DEBUG ("drop packet because signal power too Small ("<<
+                        rxPowerW<<"<"<<m_edThresholdW<<")");
+          NotifyRxDrop (packet);
+          goto maybeCcaBusy;
+        }
+      break;
+    case SpectrumYansWifiPhy::RX:
+      NS_LOG_DEBUG ("drop packet because already in Rx (power="<<
+                    rxPowerW<<"W)");
+      NotifyRxDrop (packet);
+      if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
+        {
+          // that packet will be noise _after_ the reception of the
+          // currently-received packet.
+          goto maybeCcaBusy;
+        }
+      break;
+  case SpectrumYansWifiPhy::SWITCHING:
+    NS_LOG_DEBUG ("drop packet because of channel switching");
+    NotifyRxDrop (packet);
+    /*
+     * Packets received on the upcoming channel are added to the event list
+     * during the switching state. This way the medium can be correctly sensed
+     * when the device listens to the channel for the first time after the
+     * switching e.g. after channel switching, the channel may be sensed as
+     * busy due to other devices' tramissions started before the end of
+     * the switching.
+     */
+    if (endRx > Simulator::Now () + m_state->GetDelayUntilIdle ())
+      {
+        // that packet will be noise _after_ the completion of the
+        // channel switching.
+        goto maybeCcaBusy;
+      }
+    break;
+
+  }
+
+  return;
+
+ maybeCcaBusy:
+  // We are here because we have received the first bit of a packet and we are
+  // not going to be able to synchronize on it
+  // In this model, CCA becomes busy when the aggregation of all signals as
+  // tracked by the InterferenceHelper class is higher than the CcaBusyThreshold
+
+  Time delayUntilCcaEnd = m_interference.GetEnergyDuration (m_ccaMode1ThresholdW);
+  if (!delayUntilCcaEnd.IsZero ())
+    {
+      m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
+    }
+
+  }
+}
+
+Ptr<SpectrumValue>
+SpectrumYansWifiPhy::CreateRxMask ()
+{
+  NS_LOG_FUNCTION (this);
+
+  Ptr<SpectrumValue> rxMask = Create <SpectrumValue> (SpectrumModelIsm2400MhzRes1Mhz);
+
+  // Determine which bin in our spectrum model corresponds to the
+  // centre of our channel.
+  uint16_t centreBin = m_channelFreqMhz - 2400;
+
+  const uint16_t filterHalfBandwidthMHz = 10;
+
+  (*rxMask)[centreBin] = 1;
+  for (uint16_t i = 1; i < filterHalfBandwidthMHz; i++)
+  {
+    if (centreBin >= i)
+      {
+        (*rxMask)[centreBin - i] = 0;
+      }
+
+    if ((centreBin + i) < rxMask->GetSpectrumModel ()->GetNumBands ())
+      {
+        (*rxMask)[centreBin + i] = 0;
+      }
+  }
+
+  return rxMask;
+}
+
+void
+SpectrumYansWifiPhy::SendPacket (Ptr<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 (!m_state->IsStateTx ());
+
+  Time txDuration = WifiPhy::CalculateTxDuration (packet->GetSize (),
+                                                  txMode, preamble);
+
+  if (m_state->IsStateRx ())
+    {
+      m_spectrumInterferenceTracker->EndRx ();
+      m_endRxEvent.Cancel ();
+    }
+  NotifyTxBegin (packet);
+  uint32_t dataRate500KbpsUnits = txMode.GetDataRate () / 500000;
+  bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
+  double txPowerDbm = GetPowerDbm (txPower);
+  NS_LOG_DEBUG ("Wifi Power in Dbm" << txPowerDbm);
+  NotifyPromiscSniffTx (packet, m_channelFreqMhz, m_channelNumber,
+                        dataRate500KbpsUnits, isShortPreamble,
+                        txPowerDbm, DBL_MIN);
+  m_state->SwitchToTx (txDuration, packet, txMode, preamble, txPower);
+
+  WifiPhyTag oldtag;
+  packet->RemovePacketTag(oldtag);
+  WifiPhyTag tag(txMode, preamble);
+  packet->AddPacketTag(tag);
+
+  double txPowerWatts = DbmToW (txPowerDbm);
+
+  NS_LOG_DEBUG ("Wifi Power in watts" << txPowerWatts);
+
+  Ptr<SpectrumValue> txPowerSpectrum =
+    m_spectrumValueHelper->CreateTxPowerSpectralDensity (txPowerWatts, m_channelNumber);
+
+  Ptr<PacketBurst> pb = Create<PacketBurst> ();
+  pb->AddPacket (packet);
+
+  m_channel->StartTx (pb, txPowerSpectrum, GetSpectrumType (), txDuration, GetSpectrumPhy ());
+
+}
+
+uint32_t
+SpectrumYansWifiPhy::GetNModes (void) const
+{
+  return m_deviceRateSet.size ();
+}
+WifiMode
+SpectrumYansWifiPhy::GetMode (uint32_t mode) const
+{
+  return m_deviceRateSet[mode];
+}
+uint32_t
+SpectrumYansWifiPhy::GetNTxPower (void) const
+{
+  return m_nTxPower;
+}
+
+void
+SpectrumYansWifiPhy::Configure80211a (void)
+{
+  NS_LOG_FUNCTION (this);
+  //m_interference.Configure80211aParameters ();
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate36Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate48Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate54Mbps ());
+}
+
+
+void
+SpectrumYansWifiPhy::Configure80211b (void)
+{
+  NS_LOG_FUNCTION (this);
+  //m_interference.Configure80211bParameters ();
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate1Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate2Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate5_5Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate11Mbps ());
+}
+
+void
+SpectrumYansWifiPhy::Configure80211g (void)
+{
+  NS_LOG_FUNCTION (this);
+  //m_interference.Configure80211gParameters ();
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate1Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate2Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate5_5Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate6Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate9Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetDsssRate11Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate12Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate18Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate24Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate36Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate48Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate54Mbps ());
+}
+
+void
+SpectrumYansWifiPhy::ConfigureHolland (void)
+{
+  NS_LOG_FUNCTION (this);
+  //m_interference.Configure80211aParameters ();
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate36Mbps ());
+  m_deviceRateSet.push_back (WifiPhy::GetOfdmRate54Mbps ());
+}
+
+void
+SpectrumYansWifiPhy::RegisterListener (WifiPhyListener *listener)
+{
+  m_state->RegisterListener (listener);
+}
+
+bool
+SpectrumYansWifiPhy::IsStateCcaBusy (void)
+{
+  return m_state->IsStateCcaBusy ();
+}
+
+bool
+SpectrumYansWifiPhy::IsStateIdle (void)
+{
+  return m_state->IsStateIdle ();
+}
+bool
+SpectrumYansWifiPhy::IsStateBusy (void)
+{
+  return m_state->IsStateBusy ();
+}
+bool
+SpectrumYansWifiPhy::IsStateTx (void)
+{
+  return m_state->IsStateTx ();
+}
+bool
+SpectrumYansWifiPhy::IsStateRx (void)
+{
+  return m_state->IsStateRx ();
+}
+bool
+SpectrumYansWifiPhy::IsStateSwitching (void)
+{
+  return m_state->IsStateSwitching ();
+}
+Time
+SpectrumYansWifiPhy::GetStateDuration (void)
+{
+  return m_state->GetStateDuration ();
+}
+Time
+SpectrumYansWifiPhy::GetDelayUntilIdle (void)
+{
+  return m_state->GetDelayUntilIdle ();
+}
+
+Time
+SpectrumYansWifiPhy::GetLastRxStartTime (void) const
+{
+  return m_state->GetLastRxStartTime ();
+}
+
+double
+SpectrumYansWifiPhy::GetEdThresholdW (void) const
+{
+  return m_edThresholdW;
+}
+
+double
+SpectrumYansWifiPhy::GetPowerDbm (uint8_t power) const
+{
+  NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm);
+  NS_ASSERT (m_nTxPower > 0);
+  NS_LOG_DEBUG ("m_txPowerBaseDbm" << m_txPowerBaseDbm << "m_txPowerEndDbm" << m_txPowerEndDbm << "m_nTxPower" << m_nTxPower);
+  double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / m_nTxPower;
+  return dbm;
+}
+
+void
+SpectrumYansWifiPhy::EndRx (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event)
+{
+  NS_LOG_FUNCTION (this << packet << event);
+  NS_ASSERT (IsStateRx ());
+  NS_ASSERT (event->GetEndTime () == Simulator::Now ());
+
+  struct InterferenceHelper::SnrPer snrPer;
+  snrPer = m_interference.CalculateSnrPer (event);
+
+  NS_LOG_DEBUG ("mode="<<(event->GetPayloadMode ().GetDataRate ())<<
+                ", snr="<<snrPer.snr<<", per="<<snrPer.per<<", size="<<packet->GetSize ());
+  bool rxSucceeded;
+
+  if (m_random.GetValue () > snrPer.per &&
+      m_spectrumInterferenceTracker->EndRx ())
+    {
+      NotifyRxEnd (packet);
+      uint32_t dataRate500KbpsUnits = event->GetPayloadMode ().GetDataRate () / 500000;
+      bool isShortPreamble = (WIFI_PREAMBLE_SHORT == event->GetPreambleType ());
+      double signalDbm = RatioToDb (event->GetRxPowerW ()) + 30;
+      double noiseDbm = RatioToDb(event->GetRxPowerW() / snrPer.snr) - GetRxNoiseFigure() + 30 ;
+      NotifyPromiscSniffRx (packet, m_channelFreqMhz, m_channelNumber,
+                            dataRate500KbpsUnits, isShortPreamble,
+                            signalDbm, noiseDbm);
+      m_state->SwitchFromRxEndOk (packet, snrPer.snr, event->GetPayloadMode (), event->GetPreambleType ());
+      rxSucceeded = true;
+      NS_LOG_INFO ("Reception ends in success");
+    }
+  else
+    {
+      /* failure. */
+      NotifyRxDrop (packet);
+      m_state->SwitchFromRxEndError (packet, snrPer.snr);
+      rxSucceeded = false;
+      NS_LOG_INFO ("Reception ends in failure");
+    }
+
+  // invoking a null callback is just like
+  // invoking a null function pointer:
+  // it will crash. So add check for it.
+  if (!m_rxCallback.IsNull ())
+    {
+      m_rxCallback(rxSucceeded);
+    }
+}
+
+void
+SpectrumYansWifiPhy::SetChannelNumber (uint16_t nch)
+{
+  if (Simulator::Now () == Seconds (0))
+    {
+      // this is not channel switch, this is initialization
+      NS_LOG_DEBUG("start at channel " << nch);
+      m_channelNumber = nch;
+      m_channelFreqMhz = WifiSpectrumValueHelper::GetFreqMHzForChannel (nch);
+      return;
+    }
+
+  NS_ASSERT (!IsStateSwitching());
+  switch (m_state->GetState ()) {
+  case SpectrumYansWifiPhy::RX:
+    NS_LOG_DEBUG ("drop packet because of ongoing receive at channel switch");
+    m_spectrumInterferenceTracker->EndRx ();
+    m_endRxEvent.Cancel();
+    goto switchChannel;
+    break;
+  case SpectrumYansWifiPhy::TX:
+      NS_LOG_DEBUG ("channel switching postponed until end of current transmission");
+      Simulator::Schedule (GetDelayUntilIdle(), &SpectrumYansWifiPhy::SetChannelNumber, this, nch);
+    break;
+  case SpectrumYansWifiPhy::CCA_BUSY:
+  case SpectrumYansWifiPhy::IDLE:
+    goto switchChannel;
+    break;
+  default:
+    NS_ASSERT (false);
+    break;
+  }
+
+  return;
+
+  switchChannel:
+
+  NS_LOG_DEBUG("switching channel " << m_channelNumber << " -> " << nch);
+  m_state->SwitchToChannelSwitching(m_channelSwitchDelay);
+  m_interference.EraseEvents();
+  /*
+   * Needed here to be able to correctly sensed the medium for the first
+   * time after the switching. The actual switching is not performed until
+   * after m_channelSwitchDelay. Packets received during the switching
+   * state are added to the event list and are employed later to figure
+   * out the state of the medium after the switching.
+   */
+  m_channelNumber = nch;
+  m_channelFreqMhz = WifiSpectrumValueHelper::GetFreqMHzForChannel (nch);
+}
+
+uint16_t
+SpectrumYansWifiPhy::GetChannelNumber() const
+{
+  return m_channelNumber;
+}
+
+void
+SpectrumYansWifiPhy::SetPacketReceivedCallback (RxCallback callback)
+{
+  m_rxCallback = callback;
+}
+
+Ptr<const SpectrumModel>
+SpectrumYansWifiPhy::GetRxSpectrumModel () const
+{
+  return SpectrumModelIsm2400MhzRes1Mhz;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/spectrum-yans-wifi-phy.h	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,219 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * Copyright (c) 2009 CTTC
+ *
+ * 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
+ *
+ * Original Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Ported to the Spectrum framework by Nicola Baldo <nbaldo@cttc.es> on June 2009
+ */
+
+#ifndef SPECTRUM_YANS_WIFI_PHY_H
+#define SPECTRUM_YANS_WIFI_PHY_H
+
+#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 "ns3/spectrum-phy.h"
+#include "ns3/spectrum-channel.h"
+#include "ns3/spectrum-interference.h"
+#include "wifi-phy.h"
+#include "wifi-mode.h"
+#include "wifi-preamble.h"
+#include "wifi-phy-standard.h"
+#include "interference-helper.h"
+#include "wifi-spectrum-phy-interface.h"
+#include "ns3/wifi-net-device.h"
+
+#include "wifi-spectrum-value-helper.h"
+#include "wifi-spectrum-error-model.h"
+
+namespace ns3 {
+
+class RandomUniform;
+class RxEvent;
+class WifiPhyStateHelper;
+
+/**
+ * \brief 802.11 PHY layer model
+ *
+ * This PHY implements a spectrum-aware enhancement of the 802.11a YansWifiPhy model.
+ *
+ * This PHY model depends on a channel loss and delay
+ * model as provided by the ns3::SpectrumPropagationLossModel
+ * and ns3::PropagationDelayModel classes.
+ */
+class SpectrumYansWifiPhy : public WifiPhy
+{
+public:
+
+  static TypeId GetTypeId (void);
+
+  SpectrumYansWifiPhy ();
+  virtual ~SpectrumYansWifiPhy ();
+
+  void SetChannel (Ptr<SpectrumChannel> channel);
+  void StartReceivePacket (Ptr<Packet> packet,
+                           double rxPowerDbm,
+                           WifiMode mode,
+                           WifiPreamble preamble);
+  void StartRx(Ptr<PacketBurst> burst,
+               Ptr <const SpectrumValue> rxPowerSpectrum,
+               SpectrumType st,
+               Time rxDuration);
+
+  void SetRxNoiseFigure (double noiseFigureDb);
+  void SetTxPowerStart (double start);
+  void SetTxPowerEnd (double end);
+  void SetNTxPower (uint32_t n);
+  void SetSpectrumValueHelper (Ptr<WifiSpectrumValueHelper> helper);
+  void SetEdThreshold (double threshold);
+  void SetCcaMode1Threshold (double threshold);
+  void SetErrorRateModel (Ptr<ErrorRateModel> rate);
+  void SetDevice (Ptr<Object> device);
+  void SetMobility (Ptr<Object> mobility);
+  double GetRxNoiseFigure (void) const;
+  double GetEdThreshold (void) const;
+  double GetCcaMode1Threshold (void) const;
+  Ptr<ErrorRateModel> GetErrorRateModel (void) const;
+  Ptr<Object> GetDevice (void) const;
+  Ptr<Object> GetMobility (void);
+  Ptr<SpectrumPhy> GetSpectrumPhy (void);
+  SpectrumType GetSpectrumType ();
+  void SetChannelNumber (uint16_t id);
+  uint16_t GetChannelNumber () const;
+  void CreateWifiSpectrumPhyInterface (Ptr<Node> node, Ptr<WifiNetDevice> device);
+  void SetSpectrumPhy (Ptr<WifiSpectrumPhyInterface> wifiSpectrumPhyInterface);
+
+  virtual double GetTxPowerStart (void) const;
+  virtual double GetTxPowerEnd (void) const;
+  virtual uint32_t GetNTxPower (void) const;
+  virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
+  virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
+  virtual void SendPacket (Ptr<Packet> packet, WifiMode mode,
+                           WifiPreamble preamble, uint8_t txPowerLevel);
+  virtual void RegisterListener (WifiPhyListener *listener);
+  virtual bool IsStateCcaBusy (void);
+  virtual bool IsStateIdle (void);
+  virtual bool IsStateBusy (void);
+  virtual bool IsStateTx (void);
+  virtual bool IsStateRx (void);
+  virtual bool IsStateSwitching (void);
+  virtual Time GetStateDuration (void);
+  virtual Time GetDelayUntilIdle (void);
+  virtual Time GetLastRxStartTime (void) const;
+  virtual uint32_t GetNModes (void) const;
+  virtual WifiMode GetMode (uint32_t mode) const;
+  virtual double CalculateSnr (WifiMode txMode, double ber) const;
+  virtual Ptr<WifiChannel> GetChannel (void) const;
+  virtual void ConfigureStandard (enum WifiPhyStandard standard);
+
+  typedef Callback<void,bool> RxCallback;
+  void SetPacketReceivedCallback (RxCallback callback);
+  Ptr<const SpectrumModel> GetRxSpectrumModel () const;
+
+private:
+  typedef std::vector<WifiMode> Modes;
+
+private:
+  SpectrumYansWifiPhy (const SpectrumYansWifiPhy &o);
+  virtual void DoDispose (void);
+  void Configure80211a (void);
+  void Configure80211b (void);
+  void Configure80211g (void);
+  void ConfigureHolland (void);
+  double GetEdThresholdW (void) const;
+  double GetPowerDbm (uint8_t power) const;
+  void EndRx (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event);
+
+private:
+  double   m_edThresholdW;
+  double   m_ccaMode1ThresholdW;
+  double   m_txPowerBaseDbm;
+  double   m_txPowerEndDbm;
+  uint32_t m_nTxPower;
+  uint16_t m_channelFreqMhz;
+  uint16_t m_channelNumber;
+
+  Ptr<SpectrumChannel> m_channel;
+  Ptr<Object> m_device;
+  Ptr<Object> m_mobility;
+  /**
+   * This vector holds the set of transmission modes that this
+   * WifiPhy(-derived class) can support. In conversation we call this
+   * the DeviceRateSet (not a term you'll find in the standard), and
+   * it is a superset of standard-defined parameters such as the
+   * OperationalRateSet, and the BSSBasicRateSet (which, themselves,
+   * have a superset/subset relationship).
+   *
+   * Mandatory rates relevant to this WifiPhy can be found by
+   * iterating over this vector looking for WifiMode objects for which
+   * WifiMode::IsMandatory() is true.
+   *
+   * A quick note is appropriate here (well, here is as good a place
+   * as any I can find)...
+   *
+   * In the standard there is no text that explicitly precludes
+   * production of a device that does not support some rates that are
+   * mandatory (according to the standard) for PHYs that the device
+   * happens to fully or partially support.
+   *
+   * This approach is taken by some devices which choose to only support,
+   * for example, 6 and 9 Mbps ERP-OFDM rates for cost and power
+   * consumption reasons (i.e., these devices don't need to be designed
+   * for and waste current on the increased linearity requirement of
+   * higher-order constellations when 6 and 9 Mbps more than meet their
+   * data requirements). The wording of the standard allows such devices
+   * to have an OperationalRateSet which includes 6 and 9 Mbps ERP-OFDM
+   * rates, despite 12 and 24 Mbps being "mandatory" rates for the
+   * ERP-OFDM PHY.
+   *
+   * Now this doesn't actually have any impact on code, yet. It is,
+   * however, something that we need to keep in mind for the
+   * future. Basically, the key point is that we can't be making
+   * assumptions like "the Operational Rate Set will contain all the
+   * mandatory rates".
+   */
+  WifiModeList m_deviceRateSet;
+  EventId m_endRxEvent;
+  UniformVariable m_random;
+  WifiPhyStandard m_standard;
+  Ptr<WifiPhyStateHelper> m_state;
+  InterferenceHelper m_interference;
+  Ptr<SpectrumInterference> m_spectrumInterferenceTracker;
+  Ptr<WifiSpectrumValueHelper> m_spectrumValueHelper;
+  Ptr<WifiSpectrumPhyInterface> m_wifiSpectrumPhyInterface;
+  Time m_channelSwitchDelay;
+
+  /**
+   * This method creates Rx mask
+   */
+  Ptr<SpectrumValue> CreateRxMask ();
+
+  // Tracking error model
+  Ptr<WifiSpectrumErrorModel> m_errorModel;
+
+  RxCallback m_rxCallback;
+};
+
+} // namespace ns3
+
+#endif /* SPECTRUM_YANS_WIFI_PHY_H */
--- a/src/devices/wifi/wifi-mode.h	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/wifi-mode.h	Tue Feb 15 16:00:42 2011 +0000
@@ -25,6 +25,7 @@
 #include <vector>
 #include <ostream>
 #include "ns3/attribute-helper.h"
+#include "ns3/tag.h"
 #include "ns3/wifi-phy-standard.h"
 
 namespace ns3 {
@@ -147,6 +148,7 @@
   WifiMode (std::string name);
 private:
   friend class WifiModeFactory;
+  friend class WifiPhyTag;
   WifiMode (uint32_t uid);
   uint32_t m_uid;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-phy-tag.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,86 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+#include <ns3/wifi-phy-tag.h>
+
+namespace ns3 {
+
+TypeId
+WifiPhyTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::WifiPhyTag")
+    .SetParent<Tag> ()
+    ;
+  return tid;
+}
+
+TypeId
+WifiPhyTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t
+
+WifiPhyTag::GetSerializedSize (void) const
+{
+  return 8;
+}
+
+void
+WifiPhyTag::Serialize (TagBuffer i) const
+{
+  i.WriteU32 (m_wifiModeUid);
+  i.WriteU32 (m_wifiPreamble);
+}
+
+void
+WifiPhyTag::Deserialize (TagBuffer i)
+{
+  m_wifiModeUid = i.ReadU32 ();
+  m_wifiPreamble = i.ReadU32 ();
+}
+void
+WifiPhyTag::Print (std::ostream &os) const
+{
+  os << WifiMode(m_wifiModeUid) << " " << (m_wifiPreamble ? "SP" : "LP");
+}
+
+WifiPhyTag::WifiPhyTag()
+{
+}
+
+WifiPhyTag::WifiPhyTag(WifiMode mode, WifiPreamble preamble)
+  : m_wifiModeUid(mode.GetUid()),
+    m_wifiPreamble(preamble)
+{
+}
+
+WifiMode
+WifiPhyTag::GetWifiMode (void) const
+{
+  return WifiMode(m_wifiModeUid);
+}
+
+WifiPreamble
+WifiPhyTag::GetWifiPreamble (void) const
+{
+  return ((enum WifiPreamble) m_wifiPreamble);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-phy-tag.h	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,56 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+#ifndef WIFI_PHY_TAG_H
+#define WIFI_PHY_TAG_H
+
+#include <ns3/tag.h>
+#include <ns3/wifi-mode.h>
+#include <ns3/wifi-preamble.h>
+
+namespace ns3 {
+
+/**
+ * Tag for WifiMode and WifiPreamble information to be embedded in outgoing transmissions as a PacketTag
+ *
+ */
+class WifiPhyTag : public Tag
+{
+public:
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
+
+  WifiPhyTag();
+  WifiPhyTag(WifiMode mode, WifiPreamble preamble);
+  WifiMode GetWifiMode (void) const;
+  WifiPreamble GetWifiPreamble (void) const;
+
+private:
+  uint32_t m_wifiModeUid;
+  int32_t m_wifiPreamble;
+
+};
+
+} // namespace ns3
+
+#endif /* WIFI_PHY_TAG_H */
--- a/src/devices/wifi/wifi-phy.h	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/wifi-phy.h	Tue Feb 15 16:00:42 2011 +0000
@@ -184,7 +184,8 @@
    * \param txPowerLevel a power level to use to send this packet. The real
    *        transmission power is calculated as txPowerMin + txPowerLevel * (txPowerMax - txPowerMin) / nTxLevels
    */
-  virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel) = 0;
+  virtual void SendPacket (Ptr<Packet> packet, WifiMode mode,
+                           WifiPreamble preamble, uint8_t txPowerLevel) = 0;
 
   /**
    * \param listener the new listener
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-spectrum-error-model.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,71 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Dean Armstrong
+ *
+ * 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: Dean Armstrong <deanarm@gmail.com>
+ */
+#include "wifi-spectrum-error-model.h"
+
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+
+#include "wifi-phy-tag.h"
+
+NS_LOG_COMPONENT_DEFINE ("WifiSpectrumErrorModel");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (WifiSpectrumErrorModel);
+
+void
+WifiSpectrumErrorModel::StartRx (Ptr<const Packet> p)
+{
+  NS_LOG_FUNCTION (this << p);
+  WifiPhyTag tag;
+  p->PeekPacketTag (tag);
+
+  m_rxMode = tag.GetWifiMode ();
+  m_rxPreamble = tag.GetWifiPreamble ();
+  m_rxStart = Simulator::Now ();
+
+  m_rxError = false;
+}
+
+void
+WifiSpectrumErrorModel::SetRxMask (Ptr<SpectrumValue> rxMask)
+{
+  m_rxMask = rxMask;
+}
+
+void
+WifiSpectrumErrorModel::EvaluateChunk (const SpectrumValue &sinr, Time duration)
+{
+  NS_LOG_FUNCTION (this << sinr << duration);
+
+  if (Sum ((*m_rxMask) * sinr) < 1)
+    {
+      m_rxError = true;
+    }
+}
+
+bool
+WifiSpectrumErrorModel::IsRxCorrect ()
+{
+  NS_LOG_FUNCTION (this);
+  return !m_rxError;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-spectrum-error-model.h	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,49 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Dean Armstrong
+ *
+ * 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: Dean Armstrong <deanarm@gmail.com>
+ */
+#ifndef WIFI_SPECTRUM_ERROR_MODEL_H
+#define WIFI_SPECTRUM_ERROR_MODEL_H
+
+#include "ns3/spectrum-error-model.h"
+
+#include "wifi-mode.h"
+#include "wifi-preamble.h"
+
+namespace ns3 {
+
+class WifiSpectrumErrorModel : public SpectrumErrorModel
+{
+public:
+  // inherited from SpectrumErrorModel
+  void StartRx (Ptr<const Packet> p);
+  void EvaluateChunk (const SpectrumValue &sinr, Time duration);
+  bool IsRxCorrect ();
+  void SetRxMask (Ptr<SpectrumValue> rxMask);
+private:
+  WifiMode m_rxMode;
+  WifiPreamble m_rxPreamble;
+  Time m_rxStart;
+
+  bool m_rxError;
+  Ptr<SpectrumValue> m_rxMask;
+};
+
+} // namespace ns3
+
+#endif /* WIFI_SPECTRUM_ERROR_MODEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-spectrum-phy-interface.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,101 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include <ns3/ptr.h>
+#include <ns3/object.h>
+#include <ns3/wifi-phy.h>
+#include <ns3/spectrum-phy.h>
+#include <ns3/wifi-spectrum-phy-interface.h>
+#include <ns3/log.h>
+#include <ns3/spectrum-value.h>
+#include <ns3/packet-burst.h>
+
+#include "spectrum-yans-wifi-phy.h"
+
+NS_LOG_COMPONENT_DEFINE ("WifiSpectrumPhyInterface");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (WifiSpectrumPhyInterface);
+
+TypeId
+WifiSpectrumPhyInterface::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::WifiSpectrumPhyInterface")
+    .SetParent<SpectrumPhy> ();
+  return tid;
+}
+
+void WifiSpectrumPhyInterface::SetSpectrumYansWifiPhy(Ptr<SpectrumYansWifiPhy> spectrumYansWifiPhy)
+{
+  m_spectrumYansWifiPhy = spectrumYansWifiPhy;
+}
+
+Ptr<Object>
+WifiSpectrumPhyInterface::GetDevice()
+{
+  return m_netDevice;
+}
+
+Ptr<Object>
+WifiSpectrumPhyInterface::GetMobility()
+{
+  return m_mobility;
+}
+
+void
+WifiSpectrumPhyInterface::StartRx(Ptr<PacketBurst> p, Ptr <const SpectrumValue> rxPowerSpectrum, SpectrumType st, Time duration)
+{
+  m_spectrumYansWifiPhy->StartRx(p, rxPowerSpectrum, st, duration);
+}
+
+void
+WifiSpectrumPhyInterface::SetDevice (Ptr<Object> d)
+{
+  m_netDevice = d;
+}
+
+void
+WifiSpectrumPhyInterface::SetMobility (Ptr<Object> m)
+{
+  m_mobility = m;
+}
+
+void
+WifiSpectrumPhyInterface::SetChannel (Ptr<SpectrumChannel> c)
+{
+  NS_LOG_FUNCTION (this << c);
+  m_channel = c;
+}
+
+Ptr<const SpectrumModel>
+WifiSpectrumPhyInterface::GetRxSpectrumModel () const
+{
+  if (m_txPsd)
+    {
+      return m_txPsd->GetSpectrumModel ();
+    }
+  else
+    {
+      return 0;
+    }
+}
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-spectrum-phy-interface.h	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,55 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+#ifndef WIFI_SPECTRUM_PHY_INTERFACE_H
+#define WIFI_SPECTRUM_PHY_INTERFACE_H
+
+namespace ns3 {
+
+#include<ns3/ptr.h>
+#include<ns3/object.h>
+#include<ns3/wifi-phy.h>
+#include<ns3/spectrum-phy.h>
+
+class SpectrumYansWifiPhy;
+
+class WifiSpectrumPhyInterface : public SpectrumPhy
+{
+public:
+  static TypeId GetTypeId (void);
+  void SetSpectrumYansWifiPhy(Ptr<SpectrumYansWifiPhy> phy);
+  virtual Ptr<Object> GetDevice ();
+  virtual void SetDevice (Ptr<Object> d);
+  virtual void SetMobility (Ptr<Object> m);
+  virtual Ptr<Object> GetMobility ();
+  virtual void SetChannel (Ptr<SpectrumChannel> c);
+  virtual void StartRx (Ptr<PacketBurst> p, Ptr <const SpectrumValue> rxPsd, SpectrumType st, Time duration);
+  virtual Ptr<const SpectrumModel> GetRxSpectrumModel () const;
+
+private:
+  Ptr<SpectrumYansWifiPhy> m_spectrumYansWifiPhy;
+  Ptr<Object> m_netDevice;
+  Ptr<Object> m_mobility;
+  Ptr<SpectrumChannel> m_channel;
+  Ptr<SpectrumValue> m_txPsd;
+};
+
+} // namespace ns3
+
+#endif  /* WIFI_SPECTRUM_PHY_INTERFACE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-spectrum-value-helper.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,231 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+#include "wifi-spectrum-value-helper.h"
+
+#include "ns3/spectrum-model-ism2400MHz-res1MHz.h"
+
+namespace ns3 {
+
+uint16_t
+WifiSpectrumValueHelper::GetFreqMHzForChannel (uint16_t channel)
+{
+  // Only 2.4 GHz channels 1-14 (per IEEE Std. 802.11-2007, Table
+  // 18-9) supported for now
+  NS_ASSERT (channel >= 1);
+  NS_ASSERT (channel <= 14);
+
+  // Channel 14 is a special case at 2484 MHz
+  if (channel == 14)
+    return 2484;
+
+  // Channels 1-13 are each at 2407 + channel * 5 MHz
+  return 2407 + (channel * 5);
+}
+
+Ptr<SpectrumModel> g_WifiSpectrumModel5Mhz;
+
+class WifiSpectrumModel5MhzInitializer
+{
+public:
+  WifiSpectrumModel5MhzInitializer ()
+  {
+    Bands bands;
+    for (int i = -4; i < 13+7; i++)
+      {
+        BandInfo bi;
+        bi.fl = 2407.0e6 + i * 5.0e6;
+        bi.fh = 2407.0e6 + (i+1) * 5.0e6;
+        bi.fc = (bi.fl +  bi.fh)/2;
+        bands.push_back (bi);
+      }
+    g_WifiSpectrumModel5Mhz = Create<SpectrumModel> (bands);
+  }
+} g_WifiSpectrumModel5MhzInitializerInstance;
+
+Ptr<SpectrumValue>
+WifiSpectrumValue5MhzFactory::CreateConstant (double v)
+{
+  Ptr<SpectrumValue> c = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
+  (*c) = v;
+  return c;
+}
+
+Ptr<SpectrumValue>
+WifiSpectrumValue5MhzFactory::CreateTxPowerSpectralDensity (double txPower,
+                                                            uint32_t channel)
+{
+  Ptr<SpectrumValue> txPsd = CreateConstant (0);
+
+  // since the spectrum model has a resolution of 5 MHz, we model
+  // the transmitted signal with a constant density over a 20MHz
+  // bandwidth centered on the center frequency of the channel. The
+  // transmission power outside the transmission power density is
+  // calculated considering the transmit spectrum mask, see IEEE
+  // Std. 802.11-2007, Annex I
+
+  double txPowerDensity = txPower / 20e6;
+
+  NS_ASSERT(channel >= 1);
+  NS_ASSERT(channel <= 13);
+
+  (*txPsd)[channel - 1] = txPowerDensity * 1e-4;      // -40dB
+  (*txPsd)[channel]     = txPowerDensity * 1e-4;      // -40dB
+  (*txPsd)[channel + 1] = txPowerDensity * 0.0015849; // -28dB
+  (*txPsd)[channel + 2] = txPowerDensity * 0.0015849; // -28dB
+  (*txPsd)[channel + 3] = txPowerDensity;
+  (*txPsd)[channel + 4] = txPowerDensity;
+  (*txPsd)[channel + 5] = txPowerDensity;
+  (*txPsd)[channel + 6] = txPowerDensity;
+  (*txPsd)[channel + 7] = txPowerDensity * 0.0015849; // -28dB
+  (*txPsd)[channel + 8] = txPowerDensity * 0.0015849; // -28dB
+  (*txPsd)[channel + 9] = txPowerDensity * 1e-4;      // -40dB
+  (*txPsd)[channel + 10] = txPowerDensity * 1e-4;      // -40dB
+
+  return txPsd;
+}
+
+Ptr<SpectrumValue>
+WifiSpectrumValue5MhzFactory::CreateRfFilter (uint32_t channel)
+{
+  Ptr<SpectrumValue> rf = CreateConstant (0);
+
+  NS_ASSERT(channel >= 1);
+  NS_ASSERT(channel <= 13);
+
+  (*rf)[channel + 3] = 1;
+  (*rf)[channel + 4] = 1;
+  (*rf)[channel + 5] = 1;
+  (*rf)[channel + 6] = 1;
+
+  return rf;
+}
+
+//
+// WifiSpectrumModel1MhzFactory
+//
+
+Ptr<SpectrumValue>
+WifiSpectrumValue1MhzFactory::CreateConstant (double v)
+{
+  Ptr<SpectrumValue> c = Create <SpectrumValue> (SpectrumModelIsm2400MhzRes1Mhz);
+  (*c) = v;
+  return c;
+}
+
+Ptr<SpectrumValue>
+WifiSpectrumValue1MhzFactory::CreateTxPowerSpectralDensity (double txPower, uint32_t channel)
+{
+  Ptr<SpectrumValue> txPsd = CreateConstant (0);
+
+  // Determine which bin in our spectrum model corresponds to the
+  // centre of our channel.
+  uint16_t centreBin = GetFreqMHzForChannel (channel) - 2400;
+
+  // Our transmit mask is derived through interpolation of the mask
+  // defined in the standard. Of course, real implementations will do
+  // better than this, but it seems to be the most sensible thing to
+  // use.
+  //
+  // HERE: We need to support two masks - one for each of DSSS/CCK and
+  // OFDM.
+  double mask[] = { 1,
+                    1,
+                    1,
+                    1,
+                    1,
+                    1,
+                    1,
+                    1,
+                    1,
+                    1,          //0dB
+                    0.1,        //-10
+                    0.01,       //-20dB
+                    0.0081470,  //-20.9dB
+                    0.0066374,  //-21.8dB
+                    0.0054075,  //-22.7dB
+                    0.0044055,  //-23.6dB
+                    0.0035975,  //-24.4dB
+                    0.0029309,  //-25.3dB
+                    0.0023878,  //-26.2dB
+                    0.0019454,  //-27.1dB
+                    0.0015849,  //-28dB
+                    0.0012023,  //-29.2dB
+                    0.0009120,  //-30.4dB
+                    0.0006918,  //-31.6dB
+                    0.0005248,  //-32.8dB
+                    0.0003981,  //-34dB
+                    0.0003020,  //-35.2dB
+                    0.0002291,  //-36.4dB
+                    0.0001738,  //-37.6dB
+                    0.0001318,  //-38.8dB
+                    0.0001 };   //-40dB
+
+  // To calculate the maximum power spectral density (power in our 1
+  // MHz bins), we assume that all the energy is in the 20 MHz around
+  // the centre frequency.
+  double maxPSD = txPower / 20;
+
+  for (uint16_t i = 0; i < (sizeof (mask) / sizeof (mask[0])); i++)
+  {
+    if (centreBin >= i)
+      {
+        (*txPsd)[centreBin - i] = maxPSD * mask[i];
+      }
+
+    if ((centreBin + i) < txPsd->GetSpectrumModel ()->GetNumBands ())
+      {
+        (*txPsd)[centreBin + i] = maxPSD * mask[i];
+      }
+  }
+
+  return txPsd;
+}
+
+
+Ptr<SpectrumValue>
+WifiSpectrumValue1MhzFactory::CreateRfFilter (uint32_t channel)
+{
+  Ptr<SpectrumValue> rf = CreateConstant (0);
+
+  // Determine which bin in our spectrum model corresponds to the
+  // centre of our channel.
+  uint16_t centreBin = GetFreqMHzForChannel (channel) - 2400;
+
+  // We create a brick-wall band-pass filter with width 20 MHz,
+  // centred on the channel specified.
+  const uint16_t filterHalfBandwidthMHz = 10;
+
+  for (uint16_t i = 0; i < filterHalfBandwidthMHz; i++)
+  {
+    if (centreBin >= i)
+      {
+        (*rf)[centreBin - i] = 1;
+      }
+
+    if ((centreBin + i) < rf->GetSpectrumModel ()->GetNumBands ())
+      {
+        (*rf)[centreBin + i] = 1;
+      }
+  }
+
+  return rf;
+}
+
+} //namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/wifi-spectrum-value-helper.h	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,108 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#ifndef WIFI_SPECTRUM_VALUE_HELPER_H
+#define WIFI_SPECTRUM_VALUE_HELPER_H
+
+#include <ns3/object.h>
+#include <ns3/spectrum-value.h>
+
+namespace ns3 {
+
+/**
+ * This class defines the interface for all the Wi-Fi SpectrumValue
+ * factory classes.
+ */
+class WifiSpectrumValueHelper : public Object
+{
+public:
+  /*
+   * @param channel the IEEE 802.11 channel number
+   *
+   * @return the centre frequency, in MHz, of the specified channel
+   */
+  static uint16_t GetFreqMHzForChannel (uint16_t channel);
+
+  /*
+   *
+   * @param value the constant value
+   *
+   * @return a Ptr to a newly created SpectrumValue instance which
+   * has a constant value for all frequencies
+   */
+  virtual Ptr<SpectrumValue> CreateConstant (double psd) = 0;
+
+  /*
+   *
+   * @param txPower the total TX power in W
+   * @param channel the number of the channel
+   *
+   * @return a Ptr to a newly created SpectrumValue instance which
+   * represents the TX Power Spectral Density  of a wifi device
+   * corresponding to the provided parameters
+   */
+  virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower,
+                                                           uint32_t channel) = 0;
+
+  /*
+   *
+   * @param channel the number of the channel
+   *
+   * @return a Ptr to a newly created SpectrumValue instance which
+   * represents the frequency response of the RF filter which is used
+   * by a wifi device to receive signals when tuned to a particular channel
+   */
+  virtual Ptr<SpectrumValue> CreateRfFilter (uint32_t channel) = 0;
+
+};
+
+
+/**
+ * Implements WifiSpectrumValue for the 2.4 GHz ISM band only, with a
+ * 5 MHz spectrum resolution.
+ */
+class WifiSpectrumValue5MhzFactory : public WifiSpectrumValueHelper
+{
+public:
+  // Inherited from WifiSpectrumValueHelper
+  virtual Ptr<SpectrumValue> CreateConstant (double psd);
+  virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower,
+                                                           uint32_t channel);
+  virtual Ptr<SpectrumValue> CreateRfFilter (uint32_t channel);
+
+};
+
+/**
+ * Implements WifiSpectrumValue for the 2.4 GHz ISM band only, with a
+ * 1 MHz spectrum resolution.
+ */
+class WifiSpectrumValue1MhzFactory : public WifiSpectrumValueHelper
+{
+public:
+  // Inherited from WifiSpectrumValueHelper
+  virtual Ptr<SpectrumValue> CreateConstant (double psd);
+  virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower,
+                                                           uint32_t channel);
+  virtual Ptr<SpectrumValue> CreateRfFilter (uint32_t channel);
+};
+
+} // namespace ns3
+
+#endif /*  WIFI_SPECTRUM_VALUE_HELPER_H */
--- a/src/devices/wifi/wscript	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/wscript	Tue Feb 15 16:00:42 2011 +0000
@@ -1,7 +1,7 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 def build(bld):
-    obj = bld.create_ns3_module('wifi', ['node'])
+    obj = bld.create_ns3_module('wifi', ['node', 'spectrum'])
     obj.source = [
         'wifi-information-element.cc',
         'wifi-information-element-vector.cc',
@@ -9,6 +9,7 @@
         'wifi-mode.cc',
         'ssid.cc',
         'wifi-phy.cc',
+        'wifi-phy-tag.cc',
         'wifi-phy-state-helper.cc',
         'error-rate-model.cc',
         'yans-error-rate-model.cc',
@@ -17,6 +18,10 @@
         'interference-helper.cc',
         'interference-helper-tx-duration-test.cc',
         'yans-wifi-phy.cc',
+        'spectrum-yans-wifi-phy.cc',
+        'wifi-spectrum-value-helper.cc',
+        'wifi-spectrum-phy-interface.cc',
+        'wifi-spectrum-error-model.cc',
         'yans-wifi-channel.cc',
         'wifi-mac-header.cc',
         'wifi-mac-trailer.cc',
@@ -77,8 +82,13 @@
         'wifi-preamble.h',
 	'wifi-phy-standard.h',
         'yans-wifi-phy.h',
+        'spectrum-yans-wifi-phy.h',
+        'wifi-spectrum-value-helper.h',
+        'wifi-spectrum-phy-interface.h',
+        'wifi-spectrum-error-model.h',
         'yans-wifi-channel.h',
         'wifi-phy.h',
+        'wifi-phy-tag.h',
         'interference-helper.h',
         'wifi-remote-station-manager.h',
         'ap-wifi-mac.h',
@@ -96,7 +106,6 @@
         'minstrel-wifi-manager.h',
         'wifi-mac.h',
         'regular-wifi-mac.h',
-        'wifi-phy.h',
         'supported-rates.h',
         'error-rate-model.h',
         'yans-error-rate-model.h',
--- a/src/devices/wifi/yans-wifi-phy.cc	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/yans-wifi-phy.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -494,7 +494,8 @@
 }
 
 void 
-YansWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode txMode, WifiPreamble preamble, uint8_t txPower)
+YansWifiPhy::SendPacket (Ptr<Packet> packet, WifiMode txMode,
+                         WifiPreamble preamble, uint8_t txPower)
 {
   NS_LOG_FUNCTION (this << packet << txMode << preamble << (uint32_t)txPower);
   /* Transmission can happen if:
--- a/src/devices/wifi/yans-wifi-phy.h	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/devices/wifi/yans-wifi-phy.h	Tue Feb 15 16:00:42 2011 +0000
@@ -124,7 +124,8 @@
   virtual uint32_t GetNTxPower (void) const;
   virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
   virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
-  virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel);
+  virtual void SendPacket (Ptr<Packet> packet, WifiMode mode,
+                           WifiPreamble preamble, uint8_t txPowerLevel);
   virtual void RegisterListener (WifiPhyListener *listener);
   virtual bool IsStateCcaBusy (void);
   virtual bool IsStateIdle (void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/spectrum-wifi-helper.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,362 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 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 "trace-helper.h"
+#include "spectrum-wifi-helper.h"
+#include "ns3/error-rate-model.h"
+#include "ns3/propagation-loss-model.h"
+#include "ns3/propagation-delay-model.h"
+#include "ns3/spectrum-channel.h"
+#include "ns3/spectrum-yans-wifi-phy.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/radiotap-header.h"
+#include "ns3/pcap-file-wrapper.h"
+#include "ns3/simulator.h"
+#include "ns3/config.h"
+#include "ns3/names.h"
+#include "ns3/abort.h"
+#include "ns3/log.h"
+#include "ns3/spectrum-error-model.h"
+#include "ns3/yans-error-rate-model.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("SpectrumWifiHelper");
+
+namespace ns3 {
+
+static void
+AsciiPhyTransmitSinkWithContext (
+  Ptr<OutputStreamWrapper> stream,
+  std::string context,
+  Ptr<const Packet> p,
+  WifiMode mode,
+  WifiPreamble preamble,
+  uint8_t txLevel)
+{
+  NS_LOG_FUNCTION (stream << context << p << mode << preamble << txLevel);
+  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
+}
+
+static void
+AsciiPhyTransmitSinkWithoutContext (
+  Ptr<OutputStreamWrapper> stream,
+  Ptr<const Packet> p,
+  WifiMode mode,
+  WifiPreamble preamble,
+  uint8_t txLevel)
+{
+  NS_LOG_FUNCTION (stream << p << mode << preamble << txLevel);
+  *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
+}
+
+static void
+AsciiPhyReceiveSinkWithContext (
+  Ptr<OutputStreamWrapper> stream,
+  std::string context,
+  Ptr<const Packet> p,
+  double snr,
+  WifiMode mode,
+  enum WifiPreamble preamble)
+{
+  NS_LOG_FUNCTION (stream << context << p << snr << mode << preamble);
+  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl;
+}
+
+static void
+AsciiPhyReceiveSinkWithoutContext (
+  Ptr<OutputStreamWrapper> stream,
+  Ptr<const Packet> p,
+  double snr,
+  WifiMode mode,
+  enum WifiPreamble preamble)
+{
+  NS_LOG_FUNCTION (stream << p << snr << mode << preamble);
+  *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl;
+}
+
+SpectrumWifiPhyHelper::SpectrumWifiPhyHelper ()
+  : m_channel (0),
+    m_channelNumber (1),
+    m_pcapDlt(PcapHelper::DLT_IEEE802_11)
+{
+  m_phy.SetTypeId ("ns3::SpectrumYansWifiPhy");
+}
+
+SpectrumWifiPhyHelper
+SpectrumWifiPhyHelper::Default (void)
+{
+  SpectrumWifiPhyHelper helper;
+  return helper;
+
+}
+
+void
+SpectrumWifiPhyHelper::SetChannel (Ptr<SpectrumChannel> channel)
+{
+  m_channel = channel;
+}
+void
+SpectrumWifiPhyHelper::SetChannel (std::string channelName)
+{
+  Ptr<SpectrumChannel> channel = Names::Find<SpectrumChannel> (channelName);
+  m_channel = channel;
+}
+
+void
+SpectrumWifiPhyHelper::SetChannelNumber (uint16_t nch)
+{
+  m_channelNumber = nch;
+}
+
+void
+SpectrumWifiPhyHelper::SetSpectrumValueHelper (Ptr<WifiSpectrumValueHelper> helper)
+{
+  m_spectrumValueHelper = helper;
+}
+void
+SpectrumWifiPhyHelper::Set (std::string name, const AttributeValue &v)
+{
+  m_phy.Set (name, v);
+}
+
+Ptr<WifiPhy>
+SpectrumWifiPhyHelper::Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const
+{
+  Ptr<SpectrumYansWifiPhy> phy = m_phy.Create<SpectrumYansWifiPhy> ();
+  phy->CreateWifiSpectrumPhyInterface(node, device);
+  phy->SetChannel (m_channel);
+  phy->SetChannelNumber (m_channelNumber);
+  phy->SetDevice (device);
+  phy->SetSpectrumValueHelper (m_spectrumValueHelper);
+  Ptr<ErrorRateModel> error = CreateObject<YansErrorRateModel> ();
+  phy->SetErrorRateModel(error);
+  m_channel->AddRx (phy->GetSpectrumPhy());
+
+  return phy;
+}
+
+static void
+PcapSniffEvent (
+  Ptr<PcapFileWrapper> file,
+  Ptr<const Packet> packet,
+  uint16_t channelFreqMhz,
+  uint16_t channelNumber,
+  uint32_t rate,
+  bool isShortPreamble,
+  double signalDbm,
+  double noiseDbm)
+{
+  uint32_t dlt = file->GetDataLinkType ();
+
+  switch (dlt)
+    {
+    case PcapHelper::DLT_IEEE802_11:
+      file->Write (Simulator::Now (), packet);
+      return;
+    case PcapHelper::DLT_PRISM_HEADER:
+      {
+        NS_FATAL_ERROR ("PcapSniffEvent(): DLT_PRISM_HEADER not implemented");
+        return;
+      }
+    case PcapHelper::DLT_IEEE802_11_RADIO:
+      {
+        Ptr<Packet> p = packet->Copy ();
+        RadiotapHeader header;
+        uint8_t frameFlags = RadiotapHeader::FRAME_FLAG_NONE;
+        header.SetTsft (Simulator::Now ().GetMicroSeconds ());
+
+        // Our capture includes the FCS, so we set the flag to say so.
+        frameFlags |= RadiotapHeader::FRAME_FLAG_FCS_INCLUDED;
+
+        if (isShortPreamble)
+          {
+            frameFlags |= RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE;
+          }
+
+        header.SetFrameFlags (frameFlags);
+        header.SetRate (rate);
+
+        if (channelFreqMhz < 2500)
+          {
+            header.SetChannelFrequencyAndFlags (channelFreqMhz,
+              RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ | RadiotapHeader::CHANNEL_FLAG_CCK);
+          }
+        else
+          {
+            header.SetChannelFrequencyAndFlags (channelFreqMhz,
+              RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ | RadiotapHeader::CHANNEL_FLAG_OFDM);
+          }
+
+        header.SetAntennaSignalPower (signalDbm);
+        header.SetAntennaNoisePower (noiseDbm);
+
+        p->AddHeader (header);
+        file->Write (Simulator::Now (), p);
+        return;
+      }
+    default:
+      NS_ABORT_MSG ("PcapSniffEvent(): Unexpected data link type " << dlt);
+    }
+}
+
+void
+SpectrumWifiPhyHelper::SetPcapDataLinkType (enum SupportedPcapDataLinkTypes dlt)
+{
+  switch (dlt)
+    {
+    case DLT_IEEE802_11:
+      m_pcapDlt = PcapHelper::DLT_IEEE802_11;
+      return;
+    case DLT_PRISM_HEADER:
+      m_pcapDlt = PcapHelper::DLT_PRISM_HEADER;
+      return;
+    case DLT_IEEE802_11_RADIO:
+      m_pcapDlt = PcapHelper::DLT_IEEE802_11_RADIO;
+      return;
+    default:
+      NS_ABORT_MSG ("SpectrumWifiPhyHelper::SetPcapFormat(): Unexpected format");
+    }
+}
+
+void
+SpectrumWifiPhyHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
+{
+  //
+  // All of the Pcap enable functions vector through here including the ones
+  // that are wandering through all of devices on perhaps all of the nodes in
+  // the system.  We can only deal with devices of type WifiNetDevice.
+  //
+  Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice> ();
+  if (device == 0)
+    {
+      NS_LOG_INFO ("SpectrumWifiHelper::EnablePcapInternal(): Device " << &device << " not of type ns3::WifiNetDevice");
+      return;
+    }
+
+  Ptr<WifiPhy> phy = device->GetPhy ();
+  NS_ABORT_MSG_IF (phy == 0, "SpectrumWifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set");
+
+  PcapHelper pcapHelper;
+
+  std::string filename;
+  if (explicitFilename)
+    {
+      filename = prefix;
+    }
+  else
+    {
+      filename = pcapHelper.GetFilenameFromDevice (prefix, device);
+    }
+
+  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, m_pcapDlt);
+
+  phy->TraceConnectWithoutContext ("PromiscSnifferTx", MakeBoundCallback (&PcapSniffEvent, file));
+  phy->TraceConnectWithoutContext ("PromiscSnifferRx", MakeBoundCallback (&PcapSniffEvent, file));
+}
+
+void
+SpectrumWifiPhyHelper::EnableAsciiInternal (
+  Ptr<OutputStreamWrapper> stream,
+  std::string prefix,
+  Ptr<NetDevice> nd,
+  bool explicitFilename)
+{
+  //
+  // All of the ascii enable functions vector through here including the ones
+  // that are wandering through all of devices on perhaps all of the nodes in
+  // the system.  We can only deal with devices of type CsmaNetDevice.
+  //
+  Ptr<WifiNetDevice> device = nd->GetObject<WifiNetDevice> ();
+  if (device == 0)
+    {
+      NS_LOG_INFO ("SpectrumWifiPhyHelper::EnableAsciiInternal(): Device " << device << " not of type ns3::WifiNetDevice");
+      return;
+    }
+
+  //
+  // Our trace sinks are going to use packet printing, so we have to make sure
+  // that is turned on.
+  //
+  Packet::EnablePrinting ();
+
+  uint32_t nodeid = nd->GetNode ()->GetId ();
+  uint32_t deviceid = nd->GetIfIndex ();
+  std::ostringstream oss;
+
+  //
+  // If we are not provided an OutputStreamWrapper, we are expected to create
+  // one using the usual trace filename conventions and write our traces
+  // without a context since there will be one file per context and therefore
+  // the context would be redundant.
+  //
+  if (stream == 0)
+    {
+      //
+      // Set up an output stream object to deal with private ofstream copy
+      // constructor and lifetime issues.  Let the helper decide the actual
+      // name of the file given the prefix.
+      //
+      AsciiTraceHelper asciiTraceHelper;
+
+      std::string filename;
+      if (explicitFilename)
+        {
+          filename = prefix;
+        }
+      else
+        {
+          filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
+        }
+
+      Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
+      //
+      // We could go poking through the phy and the state looking for the
+      // correct trace source, but we can let Config deal with that with
+      // some search cost.  Since this is presumably happening at topology
+      // creation time, it doesn't seem much of a price to pay.
+      //
+      oss.str ("");
+      oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk";
+      Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithoutContext, theStream));
+
+      oss.str ("");
+      oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx";
+      Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithoutContext, theStream));
+
+      return;
+    }
+
+  //
+  // If we are provided an OutputStreamWrapper, we are expected to use it, and
+  // to provide a context.  We are free to come up with our own context if we
+  // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
+  // compatibility and simplicity, we just use Config::Connect and let it deal
+  // with coming up with a context.
+  //
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithContext, stream));
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/spectrum-wifi-helper.h	Tue Feb 15 16:00:42 2011 +0000
@@ -0,0 +1,159 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 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 SPECTRUM_WIFI_HELPER_H
+#define SPECTRUM_WIFI_HELPER_H
+
+#include "wifi-helper.h"
+#include "trace-helper.h"
+#include "ns3/spectrum-channel.h"
+#include "ns3/wifi-spectrum-value-helper.h"
+#include "ns3/deprecated.h"
+
+namespace ns3 {
+
+/**
+ * \brief Make it easy to create and manage PHY objects for the spectrum model.
+ * The Pcap and ascii traces generated by the EnableAscii and EnablePcap methods defined
+ * in this class correspond to PHY-level traces and come to us via WifiPhyHelper
+ *
+ */
+class SpectrumWifiPhyHelper : public WifiPhyHelper,
+                          public PcapHelperForDevice, public AsciiTraceHelperForDevice
+{
+public:
+  /**
+   * Create a phy helper without any parameter set. The user must set
+   * them all to be able to call Install later.
+   */
+  SpectrumWifiPhyHelper ();
+
+  /**
+   * Create a phy helper in a default working state.
+   */
+  static SpectrumWifiPhyHelper Default (void);
+
+  /**
+   * \param channel the channel to associate to this helper
+   *
+   * Every PHY created by a call to Install is associated to this channel.
+   */
+  void SetChannel (Ptr<SpectrumChannel> channel);
+
+  /**
+   * \param channelnum the channel number to which created PHYs will be tuned
+   */
+  void SetChannelNumber (uint16_t nch);
+
+  /**
+   * \param helper the Wi-Fi spectrum helper to be used in created PHYs
+   *
+   * Every PHY created by a call to Install is associated to this helper.
+   */
+  void SetSpectrumValueHelper (Ptr<WifiSpectrumValueHelper> helper);
+
+  /**
+   * \param channelName The name of the channel to associate to this helper
+   *
+   * Every PHY created by a call to Install is associated to this channel.
+   */
+  void SetChannel (std::string channelName);
+  /**
+   * \param name the name of the attribute to set
+   * \param v the value of the attribute
+   *
+   * Set an attribute of the underlying PHY object.
+   */
+  void Set (std::string name, const AttributeValue &v);
+
+  /**
+   * An enumeration of the pcap data link types (DLTs) which this helper
+   * supports.  See http://wiki.wireshark.org/Development/LibpcapFileFormat
+   * for more information on these formats.
+   */
+  enum SupportedPcapDataLinkTypes {
+    DLT_IEEE802_11       = PcapHelper::DLT_IEEE802_11,       /**< IEEE 802.11 Wireless LAN headers on packets */
+    DLT_PRISM_HEADER     = PcapHelper::DLT_PRISM_HEADER,     /**< Include Prism monitor mode information */
+    DLT_IEEE802_11_RADIO = PcapHelper::DLT_IEEE802_11_RADIO  /**< Include Radiotap link layer information */
+  };
+
+  /**
+   * Set the data link type of PCAP traces to be used. This function has to be
+   * called before EnablePcap(), so that the header of the pcap file can be
+   * written correctly.
+   *
+   * @see SupportedPcapDataLinkTypes
+   *
+   * @param dlt The data link type of the pcap file (and packets) to be used
+   */
+  void SetPcapDataLinkType (enum SupportedPcapDataLinkTypes dlt);
+
+private:
+  /**
+   * \param node the node on which we wish to create a wifi PHY
+   * \param device the device within which this PHY will be created
+   * \returns a newly-created PHY object.
+   *
+   * This method implements the pure virtual method defined in \ref ns3::WifiPhyHelper.
+   */
+  virtual Ptr<WifiPhy> Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const;
+
+  /**
+   * @brief Enable pcap output the indicated net device.
+   *
+   * NetDevice-specific implementation mechanism for hooking the trace and
+   * writing to the trace file.
+   *
+   * @param prefix Filename prefix to use for pcap files.
+   * @param nd Net device for which you want to enable tracing.
+   * @param promiscuous If true capture all possible packets available at the device.
+   * @param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  virtual void EnablePcapInternal (std::string prefix,
+                                   Ptr<NetDevice> nd,
+                                   bool promiscuous,
+                                   bool explicitFilename);
+
+  /**
+   * \brief Enable ascii trace output on the indicated net device.
+   * \internal
+   *
+   * NetDevice-specific implementation mechanism for hooking the trace and
+   * writing to the trace file.
+   *
+   * \param stream The output stream object to use when logging ascii traces.
+   * \param prefix Filename prefix to use for ascii trace files.
+   * \param nd Net device for which you want to enable tracing.
+   */
+  virtual void EnableAsciiInternal (Ptr<OutputStreamWrapper> stream,
+                                    std::string prefix,
+                                    Ptr<NetDevice> nd,
+                                    bool explicitFilename);
+
+  ObjectFactory m_phy;
+  ObjectFactory m_errorRateModel;
+  Ptr<SpectrumChannel> m_channel;
+  uint16_t m_channelNumber;
+  Ptr<WifiSpectrumValueHelper> m_spectrumValueHelper;
+  uint32_t m_pcapDlt;
+};
+
+} // namespace ns3
+
+#endif /* SPECTRUM_WIFI_HELPER_H */
--- a/src/helper/wifi-helper.cc	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/helper/wifi-helper.cc	Tue Feb 15 16:00:42 2011 +0000
@@ -153,6 +153,7 @@
   LogComponentEnable ("RegularWifiMac", LOG_LEVEL_ALL);
   LogComponentEnable ("RraaWifiManager", LOG_LEVEL_ALL);
   LogComponentEnable ("StaWifiMac", LOG_LEVEL_ALL);
+  LogComponentEnable ("SpectrumYansWifiPhy", LOG_LEVEL_ALL);
   LogComponentEnable ("SupportedRates", LOG_LEVEL_ALL);
   LogComponentEnable ("WifiChannel", LOG_LEVEL_ALL);
   LogComponentEnable ("WifiPhyStateHelper", LOG_LEVEL_ALL);
--- a/src/helper/wscript	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/helper/wscript	Tue Feb 15 16:00:42 2011 +0000
@@ -44,6 +44,7 @@
         'wimax-helper.cc',
         'topology-reader-helper.cc',
         'bulk-send-helper.cc',
+        'spectrum-wifi-helper.cc',
         ]
 
     headers = bld.new_task_gen('ns3header')
@@ -91,6 +92,7 @@
         'wimax-helper.h',
         'topology-reader-helper.h',
         'bulk-send-helper.h',
+        'spectrum-wifi-helper.h',
         ]
 
     env = bld.env_of_name('default')
--- a/src/spectrum/model/wifi-spectrum-value-helper.cc	Tue Feb 15 15:28:15 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2009 CTTC
- *
- * 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: Nicola Baldo <nbaldo@cttc.es>
- */
-
-
-#include "wifi-spectrum-value-helper.h"
-
-namespace ns3 {
-
-  
-Ptr<SpectrumModel> g_WifiSpectrumModel5Mhz;
-
-WifiSpectrumValueHelper::~WifiSpectrumValueHelper ()
-{
-}
-
-WifiSpectrumValue5MhzFactory::~WifiSpectrumValue5MhzFactory ()
-{
-}
-
-class WifiSpectrumModel5MhzInitializer
-{
-public:
-  WifiSpectrumModel5MhzInitializer ()
-  {
-    Bands bands;
-    for (int i = -4; i < 13+7; i++)
-      {
-        BandInfo bi;
-        bi.fl = 2407.0e6 + i * 5.0e6;
-        bi.fh = 2407.0e6 + (i+1) * 5.0e6;
-        bi.fc = (bi.fl +  bi.fh)/2;
-        bands.push_back (bi);
-      }
-    g_WifiSpectrumModel5Mhz = Create<SpectrumModel> (bands);
-  }
-} g_WifiSpectrumModel5MhzInitializerInstance;
-
-
-
-Ptr<SpectrumValue> 
-WifiSpectrumValue5MhzFactory::CreateConstant (double v)
-{  
-  Ptr<SpectrumValue> c = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
-  (*c) = v;
-  return c;
-}
-
-
-Ptr<SpectrumValue> 
-WifiSpectrumValue5MhzFactory::CreateTxPowerSpectralDensity (double txPower, uint32_t channel)
-{  
-  Ptr<SpectrumValue> txPsd = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
-
-  // since the spectrum model has a resolution of 5 MHz, we model
-  // the transmitted signal with a constant density over a 20MHz
-  // bandwidth centered on the center frequency of the channel. The
-  // transmission power outside the transmission power density is
-  // calculated considering the transmit spectrum mask, see IEEE
-  // Std. 802.11-2007, Annex I
-
-  double txPowerDensity = txPower / 20e6; 
-
-  NS_ASSERT(channel >= 1);
-  NS_ASSERT(channel <= 13);
-
-  (*txPsd)[channel - 1] = txPowerDensity * 1e-4;      // -40dB
-  (*txPsd)[channel]     = txPowerDensity * 1e-4;      // -40dB
-  (*txPsd)[channel + 1] = txPowerDensity * 0.0015849; // -28dB
-  (*txPsd)[channel + 2] = txPowerDensity * 0.0015849; // -28dB
-  (*txPsd)[channel + 3] = txPowerDensity;
-  (*txPsd)[channel + 4] = txPowerDensity;
-  (*txPsd)[channel + 5] = txPowerDensity;
-  (*txPsd)[channel + 6] = txPowerDensity;
-  (*txPsd)[channel + 7] = txPowerDensity * 0.0015849; // -28dB
-  (*txPsd)[channel + 8] = txPowerDensity * 0.0015849; // -28dB
-  (*txPsd)[channel + 9] = txPowerDensity * 1e-4;      // -40dB
-  (*txPsd)[channel + 10] = txPowerDensity * 1e-4;      // -40dB
-
-  return txPsd;
-}
-
-
-Ptr<SpectrumValue> 
-WifiSpectrumValue5MhzFactory::CreateRfFilter (uint32_t channel)
-{  
-  Ptr<SpectrumValue> rf = Create <SpectrumValue> (g_WifiSpectrumModel5Mhz);
-
-  NS_ASSERT(channel >= 1);
-  NS_ASSERT(channel <= 13);
-
-  (*rf)[channel - 1] = 1;
-  (*rf)[channel    ] = 1;
-  (*rf)[channel + 1] = 1;
-  (*rf)[channel + 2] = 1;
-
-  return rf;
-}
-
-
-} //namespace ns3
--- a/src/spectrum/model/wifi-spectrum-value-helper.h	Tue Feb 15 15:28:15 2011 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2009 CTTC
- *
- * 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: Nicola Baldo <nbaldo@cttc.es>
- */
-
-#ifndef WIFI_SPECTRUM_VALUE_HELPER_H
-#define WIFI_SPECTRUM_VALUE_HELPER_H
-
-
-#include <ns3/spectrum-value.h>
-
-namespace ns3 {
-
-
-
-/** 
- * this abstract class defines the interface for interacting with all WifiSpectrumValue implementations.
- *
- */
-class WifiSpectrumValueHelper 
-{
-public:
-  virtual ~WifiSpectrumValueHelper ();
-  /*
-   *
-   * @param value the constant value
-   * 
-   * @return a Ptr to a newly created SpectrumValue instance which
-   * has a constant value for all frequencies
-   */
-  virtual Ptr<SpectrumValue> CreateConstant (double psd) = 0;
-
-  /*
-   *
-   * @param txPower the total TX power in W
-   * @param channel the number of the channel 
-   * 
-   * @return a Ptr to a newly created SpectrumValue instance which
-   * represents the TX Power Spectral Density  of a wifi device
-   * corresponding to the provided parameters
-   */
-  virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower, uint32_t channel) = 0;
-
-  /*
-   *
-   * @param channel the number of the channel 
-   * 
-   * @return a Ptr to a newly created SpectrumValue instance which
-   * represents the frequency response of the RF filter which is used
-   * by a wifi device to receive signals when tuned to a particular channel
-   */
-  virtual Ptr<SpectrumValue> CreateRfFilter (uint32_t channel) = 0;
-  
-};
-
-
-
-/** 
- * Implements WifiSpectrumValue for the 2.4 GHz ISM band only, with a
- * 5 MHz spectrum resolution.
- *
- */
-class WifiSpectrumValue5MhzFactory
-{
-public:
-  virtual ~WifiSpectrumValue5MhzFactory ();
-  // inherited from WifiSpectrumValue
-  virtual Ptr<SpectrumValue> CreateConstant (double psd);
-  virtual Ptr<SpectrumValue> CreateTxPowerSpectralDensity (double txPower, uint32_t channel);
-  virtual Ptr<SpectrumValue> CreateRfFilter (uint32_t channel);
-
-};
-
-
-  
-} //namespace ns3
-
-
-
-#endif /*  WIFI_SPECTRUM_VALUE_HELPER_H */
--- a/src/spectrum/wscript	Tue Feb 15 15:28:15 2011 +0000
+++ b/src/spectrum/wscript	Tue Feb 15 16:00:42 2011 +0000
@@ -18,7 +18,6 @@
         'model/spectrum-error-model.cc',
         'model/spectrum-model-ism2400MHz-res1MHz.cc',
         'model/spectrum-model-300kHz-300GHz-log.cc', 
-        'model/wifi-spectrum-value-helper.cc',
         'model/waveform-generator.cc',
         'model/spectrum-analyzer.cc',
         'model/aloha-noack-mac-header.cc',
@@ -51,7 +50,6 @@
         'model/spectrum-error-model.h',
         'model/spectrum-model-ism2400MHz-res1MHz.h',
         'model/spectrum-model-300kHz-300GHz-log.h',
-        'model/wifi-spectrum-value-helper.h',
         'model/waveform-generator.h',       
         'model/spectrum-analyzer.h',
         'model/aloha-noack-mac-header.h',