Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(133)

Unified Diff: src/contrib/physim-wifi/model/physim-wifi-phy.cc

Issue 2173042: NS-3: New and accurate physical layer for IEEE 802.11 OFDM called PhySim-WiFi
Patch Set: Created 13 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/contrib/physim-wifi/model/physim-wifi-phy.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/contrib/physim-wifi/model/physim-wifi-phy.cc
@@ -0,0 +1,1521 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA, 2009-2010 Jens Mittag, Stylianos Papanastasiou
+ *
+ * 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
+ *
+ * Based on yans-wifi-phy.h by:
+ * Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Major modifications by:
+ * Jens Mittag <jens.mittag@kit.edu>
+ * Stylianos Papanastasiou <stylianos@gmail.com>
+ */
+
+#include "physim-wifi-phy.h"
+#include "physim-wifi-channel.h"
+#include "physim-ofdm-symbolcreator.h"
+#include "physim-wifi-phy-state-helper.h"
+#include "ns3/wifi-mode.h"
+#include "ns3/wifi-preamble.h"
+#include "ns3/error-rate-model.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/boolean.h"
+#include "ns3/uinteger.h"
+#include "ns3/integer.h"
+#include "ns3/string.h"
+#include "ns3/object-factory.h"
+#include "ns3/enum.h"
+#include "ns3/pointer.h"
+#include "ns3/net-device.h"
+#include "ns3/trace-source-accessor.h"
+
+NS_LOG_COMPONENT_DEFINE ("PhySimWifiPhy");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (PhySimWifiPhy);
+
+const double PhySimWifiPhy::m_normFactor = sqrt (64.0 * 64.0 / 52.0);
+itpp::cvec PhySimWifiPhy::m_cachedPreamble;
+bool PhySimWifiPhy::m_rngReset;
+
+TypeId
+PhySimWifiPhy::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::PhySimWifiPhy")
+ .SetParent<WifiPhy> ()
+ .AddConstructor<PhySimWifiPhy> ()
+ .AddAttribute ("CcaModelThreshold",
+ "The energy of a received signal should be higher than this threshold (dbm) to allow "
+ "the PHY layer to declare CCA BUSY state. According to the IEEE 802.11 standard, this is "
+ "the minimum receiver sensitivity at lowest modulation plus 20 dB, which makes it -62 dBm"
+ "for 20 MHz channels, -65 dBm for 10 MHz channels and -68 dBm for 5 MHz channels",
+ DoubleValue (-62.0),
+ MakeDoubleAccessor (&PhySimWifiPhy::m_ccaMode1ThresholdDbm),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("EnergyDetectionThreshold",
+ "The energy detection that is used to decide whether the incoming frame is considered for reception "
+ "at all. If the energy is too low, it will be part of the thermal noise anyways.",
+ DoubleValue (-104.0),
+ MakeDoubleAccessor (&PhySimWifiPhy::m_edThresholdDbm),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("TxGain",
+ "Transmission gain (dB).",
+ DoubleValue (0.0),
+ MakeDoubleAccessor (&PhySimWifiPhy::m_txGainDb),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("RxGain",
+ "Reception gain (dB).",
+ DoubleValue (0.0),
+ MakeDoubleAccessor (&PhySimWifiPhy::m_rxGainDb),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("TxPowerLevels",
+ "Number of transmission power levels available between "
+ "TxPowerBase and TxPowerEnd included.",
+ UintegerValue (1),
+ MakeUintegerAccessor (&PhySimWifiPhy::m_nTxPower),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("TxPowerStart",
+ "Minimum available transmission level (dbm).",
+ DoubleValue (16.0206),
+ MakeDoubleAccessor (&PhySimWifiPhy::m_txPowerBaseDbm),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("TxPowerEnd",
+ "Maximum available transmission level (dbm).",
+ DoubleValue (16.0206),
+ MakeDoubleAccessor (&PhySimWifiPhy::m_txPowerEndDbm),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("NormalizeOFDMSymbols",
+ "Flag indicating whether we will normalize the OFDM symbols to unit power",
+ BooleanValue (true),
+ MakeBooleanAccessor (&PhySimWifiPhy::m_normalizeOfdmBlocks),
+ MakeBooleanChecker ())
+ .AddAttribute ("CalculateHeaderSinr",
+ "Flag indicating whether to calculate the Header SINR or not (will be stored inside of PhySimWifiPhyTag for evaluation purposes, but increases processing time)",
+ BooleanValue (false),
+ MakeBooleanAccessor (&PhySimWifiPhy::m_calculateHeaderSinr),
+ MakeBooleanChecker ())
+ .AddAttribute ("CalculatePayloadSinr",
+ "Flag indicating whether to calculate the Payload SINR or not (will be stored inside of PhySimWifiPhyTag for evaluation purposes, but increases processing time)",
+ BooleanValue (false),
+ MakeBooleanAccessor (&PhySimWifiPhy::m_calculatePayloadSinr),
+ MakeBooleanChecker ())
+ .AddAttribute ("CalculateOverallSinr",
+ "Flag indicating whether to calculate the overall and average SINR of the frame or not (will be stored inside of PhySimWifiPhyTag for evaluation purposes, but increases processing time)",
+ BooleanValue (false),
+ MakeBooleanAccessor (&PhySimWifiPhy::m_calculateOverallSinr),
+ MakeBooleanChecker ())
+ .AddAttribute ("Standard",
+ "The standard chosen configures a set of transmission modes and some PHY-specific constants.",
+ EnumValue (WIFI_PHY_STANDARD_80211a),
+ MakeEnumAccessor (&PhySimWifiPhy::ConfigureStandard),
+ MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a - 20 MHz",
+ WIFI_PHY_STANDARD_80211_10Mhz, "802.11a - 10 MHz",
+ WIFI_PHY_STANDARD_80211_5Mhz, "802.11a - 5 MHz",
+ WIFI_PHY_STANDARD_80211p_CCH, "802.11p - CCH",
+ WIFI_PHY_STANDARD_80211p_SCH, "802.11p - SCH"))
+ .AddAttribute ("State", "The state of the PHY layer",
+ PointerValue (),
+ MakePointerAccessor (&PhySimWifiPhy::m_state),
+ MakePointerChecker<PhySimWifiPhyStateHelper> ())
+ .AddAttribute ("SymbolTime",
+ "Duration of an OFDM symbol (e.g. 4 microseconds for 20 MHz channels, 8 microseconds for 10 MHz channels)",
+ TimeValue (MicroSeconds (4)),
+ MakeTimeAccessor (&PhySimWifiPhy::SetSymbolTime),
+ MakeTimeChecker ())
+ .AddTraceSource ("PreambleOk",
+ "A preamble has been detected successfully.",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_preambleOkTrace))
+ .AddTraceSource ("PreambleError",
+ "A preamble has not been detected successfully.",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_preambleErrorTrace))
+ .AddTraceSource ("RxOk",
+ "A packet has been received successfully.",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_rxOkTrace))
+ .AddTraceSource ("RxError",
+ "A packet has not been received successfully.",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_rxErrorTrace))
+ .AddTraceSource ("HeaderOk",
+ "A signal header has been decoded successfully.",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_headerOkTrace))
+ .AddTraceSource ("HeaderError",
+ "A signal header has not been decoded successfully.",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_headerErrorTrace))
+ .AddTraceSource ("Tx", "Packet transmission is starting.",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_txTrace))
+ .AddTraceSource ("CcaBusyStart", "Start of a CCA busy phase",
+ MakeTraceSourceAccessor (&PhySimWifiPhy::m_ccaBusyStartTrace))
+ .AddAttribute ("TxCenterFrequencyTolerance",
+ "The transmitted center frequency tolerance (in ppm) according to 17.3.9.4 of the 802.11 standard."
+ "(defined as 20ppm for 20MHz and 10Mhz channels, 10ppm for 5Mhz channels)",
+ UintegerValue (20),
+ MakeUintegerAccessor (&PhySimWifiPhy::m_txCenterFreqTolerance),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("FixedPhaseOffset",
+ "Defines a fixed phase offset for oscillator effects instead of using a random integer value within the range specified by the "
+ "attribute 'TxCenterFrequencyTolerance'. If this value is set to 0 (default), it is ignored.",
+ UintegerValue (0),
+ MakeUintegerAccessor (&PhySimWifiPhy::m_fixedPhaseOffset),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("Frequency",
+ "The carrier frequency at which the communication is performed (in Hz)",
+ DoubleValue (5.150e9),
+ MakeDoubleAccessor (&PhySimWifiPhy::m_frequency),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("ChannelEstimator",
+ "Defines the channel estimator implementation which shall be used for this Phy",
+ StringValue ("ns3::PhySimChannelFrequencyOffsetEstimator"),
+ MakeStringAccessor (&PhySimWifiPhy::SetChannelEstimator),
+ MakeStringChecker ())
+ .AddAttribute ("SignalDetector",
+ "Defines the signal detector implementation which shall be used for this Phy",
+ StringValue ("ns3::PhySimSignalDetector"),
+ MakeStringAccessor (&PhySimWifiPhy::SetSignalDetector),
+ MakeStringChecker ())
+ ;
+ return tid;
+}
+
+PhySimWifiPhy::PhySimWifiPhy ()
+ : m_endRxEvent (),
+ m_random (0.0, 1.0),
+ m_estimator (0)
+{
+ NS_LOG_FUNCTION (this);
+ m_state = CreateObject<PhySimWifiPhyStateHelper> ();
+
+ m_shortSymbol
+ = sqrt (13.0 / 6.0) * itpp::cvec ("0 0 (1,1) 0 0 0 (-1,-1) 0 0 0 (1,1) 0 0 0 (-1,-1) 0 0 0 (-1,-1) 0 0 0 (1,1) 0 0 0 0 0 0 0 (-1,-1) 0 0 0 (-1,-1) 0 0 0 (1,1) 0 0 0 (1,1) 0 0 0 (1,1) 0 0 0 (1,1) 0 0");
+ m_longSymbol
+ = "1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 1 1 -1 -1 1 1 -1 1 -1 1 1 1 1 0 1 -1 -1 1 1 -1 1 -1 1 -1 -1 -1 -1 -1 1 1 -1 -1 1 -1 1 -1 1 1 1 1";
+
+ /*
+ * Define the binary values of the 4-bit rate field in an array.
+ * Element
+ * 0 --> BPSK_1/2,
+ * 1 --> BPSK_2/3,
+ * 2 --> QPSK_1/2,
+ * 3 --> QPSK_3/4,
+ * 4 --> QAM16_1/2
+ * 5 --> QAM16_3/4,
+ * 6 --> QAM64_2/3,
+ * 7 --> QAM64_3/4
+ */
+
+ m_ofdmSymbolCreator = CreateObject<PhySimOFDMSymbolCreator> ();
+ m_convEncoder = CreateObject<PhySimConvolutionalEncoder> ();
+ m_interleaver = CreateObject<PhySimBlockInterleaver> ();
+ m_scrambler = CreateObject<PhySimScrambler> ();
+ m_interference = CreateObject<PhySimInterferenceHelper> ();
+
+ m_estimator = m_ofdmSymbolCreator->GetChannelEstimator ();
+}
+
+PhySimWifiPhy::~PhySimWifiPhy ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+void
+PhySimWifiPhy::SetChannelEstimator (std::string type)
+{
+ m_ofdmSymbolCreator->SetChannelEstimator (type);
+ m_estimator = m_ofdmSymbolCreator->GetChannelEstimator ();
+}
+
+void
+PhySimWifiPhy::SetSignalDetector (std::string type)
+{
+ ObjectFactory factory;
+ factory.SetTypeId (type);
+ m_signalDetector = factory.Create<PhySimSignalDetector> ();
+}
+
+void
+PhySimWifiPhy::SetSymbolTime (Time duration)
+{
+ NS_LOG_FUNCTION (this << duration);
+ m_symbolTime = duration;
+ m_sampleTime = 0.05e-6 * (duration.GetMicroSeconds () / 4);
+ m_interference->SetSymbolTime (duration);
+}
+
+void
+PhySimWifiPhy::SetChannel (Ptr<PhySimWifiChannel> channel)
+{
+ m_channel = channel;
+ m_channel->Add (this);
+}
+
+void
+PhySimWifiPhy::SetDevice (Ptr<Object> device)
+{
+ m_device = device;
+ m_state->SetNetDevice (device->GetObject<NetDevice> ());
+}
+
+void
+PhySimWifiPhy::SetMobility (Ptr<Object> mobility)
+{
+ m_mobility = mobility;
+}
+
+Ptr<Object>
+PhySimWifiPhy::GetDevice (void) const
+{
+ return m_device;
+}
+
+Ptr<Object>
+PhySimWifiPhy::GetMobility (void)
+{
+ return m_mobility;
+}
+
+double
+PhySimWifiPhy::GetTxPowerStart (void) const
+{
+ return m_txPowerBaseDbm;
+}
+
+double
+PhySimWifiPhy::GetTxPowerEnd (void) const
+{
+ return m_txPowerEndDbm;
+}
+
+uint32_t
+PhySimWifiPhy::GetNTxPower (void) const
+{
+ return m_nTxPower;
+}
+
+void
+PhySimWifiPhy::SetReceiveOkCallback (WifiPhy::RxOkCallback callback)
+{
+ m_state->SetReceiveOkCallback (callback);
+}
+
+void
+PhySimWifiPhy::SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback)
+{
+ m_state->SetReceiveErrorCallback (callback);
+}
+
+void
+PhySimWifiPhy::RegisterListener (WifiPhyListener *listener)
+{
+ m_state->RegisterListener (listener);
+}
+
+bool
+PhySimWifiPhy::IsStateCcaBusy (void)
+{
+ return m_state->IsStateCcaBusy ();
+}
+
+bool
+PhySimWifiPhy::IsStateIdle (void)
+{
+ return m_state->IsStateIdle ();
+}
+
+bool
+PhySimWifiPhy::IsStateBusy (void)
+{
+ return m_state->IsStateBusy ();
+}
+
+bool
+PhySimWifiPhy::IsStateRx (void)
+{
+ return m_state->IsStateSync ();
+}
+
+bool
+PhySimWifiPhy::IsStateTx (void)
+{
+ return m_state->IsStateTx ();
+}
+
+bool
+PhySimWifiPhy::IsStateSwitching (void)
+{
+ // TODO: Implement channel switching support once multi-channel operation is supported
+ return false;
+}
+
+Time
+PhySimWifiPhy::GetStateDuration (void)
+{
+ return m_state->GetStateDuration ();
+}
+
+Time
+PhySimWifiPhy::GetDelayUntilIdle (void)
+{
+ return m_state->GetDelayUntilIdle ();
+}
+
+Time
+PhySimWifiPhy::GetLastRxStartTime (void) const
+{
+ return m_state->GetLastRxStartTime ();
+}
+
+Time
+PhySimWifiPhy::CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const
+{
+ return m_interference->CalculateTxDuration (size, payloadMode, preamble);
+}
+
+uint32_t
+PhySimWifiPhy::GetNModes (void) const
+{
+ return m_deviceRateSet.size ();
+}
+
+WifiMode
+PhySimWifiPhy::GetMode (uint32_t mode) const
+{
+ return m_deviceRateSet[mode];
+}
+
+double
+PhySimWifiPhy::CalculateSnr (WifiMode txMode, double ber) const
+{
+ // TODO: maybe fix that and return average SINR of the frame (if possible)
+ // return m_interference->GetErrorRateModel ()->CalculateSnr (txMode, ber);
+ return 0.0;
+}
+
+void
+PhySimWifiPhy::SetChannelNumber (uint16_t id)
+{
+ // TODO: Implement channel switching support once multi-channel operation is supported
+}
+
+uint16_t
+PhySimWifiPhy::GetChannelNumber () const
+{
+ // TODO: Implement channel switching support once multi-channel operation is supported
+ return 0;
+}
+
+Ptr<WifiChannel>
+PhySimWifiPhy::GetChannel (void) const
+{
+ return m_channel;
+}
+
+void
+PhySimWifiPhy::ConfigureStandard (enum WifiPhyStandard standard)
+{
+ NS_LOG_FUNCTION (this << standard);
+ m_deviceRateSet.clear ();
+ switch (standard)
+ {
+ case WIFI_PHY_STANDARD_80211a:
+ Configure80211a ();
+ break;
+ case WIFI_PHY_STANDARD_80211_10Mhz:
+ Configure80211a_10Mhz ();
+ break;
+ case WIFI_PHY_STANDARD_80211_5Mhz:
+ Configure80211a_5Mhz ();
+ break;
+ case WIFI_PHY_STANDARD_80211p_CCH:
+ Configure80211p_CCH ();
+ break;
+ case WIFI_PHY_STANDARD_80211p_SCH:
+ Configure80211p_SCH ();
+ break;
+ default:
+ NS_ASSERT (false);
+ break;
+ }
+}
+
+void
+PhySimWifiPhy::DoDispose (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_channel = 0;
+ m_deviceRateSet.clear ();
+ m_device = 0;
+}
+
+void
+PhySimWifiPhy::Configure80211a (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_frequency = 5.2e9;
+ SetSymbolTime ( MicroSeconds (4) );
+ m_txCenterFreqTolerance = 20;
+ m_ccaMode1ThresholdDbm = -62.0;
+ 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
+PhySimWifiPhy::Configure80211a_10Mhz (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_frequency = 5.2e9;
+ SetSymbolTime ( MicroSeconds (8) );
+ m_txCenterFreqTolerance = 20;
+ m_ccaMode1ThresholdDbm = -65.0;
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate3MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate4_5MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate27MbpsBW10MHz ());
+}
+
+void
+PhySimWifiPhy::Configure80211a_5Mhz (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_frequency = 5.2e9;
+ SetSymbolTime ( MicroSeconds (16) );
+ m_txCenterFreqTolerance = 10;
+ m_ccaMode1ThresholdDbm = -68.0;
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate1_5MbpsBW5MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate2_25MbpsBW5MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate3MbpsBW5MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate4_5MbpsBW5MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6MbpsBW5MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9MbpsBW5MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12MbpsBW5MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate13_5MbpsBW5MHz ());
+}
+
+void
+PhySimWifiPhy::Configure80211p_CCH (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_frequency = 5.9e9;
+ SetSymbolTime ( MicroSeconds (8) );
+ m_txCenterFreqTolerance = 20;
+ m_ccaMode1ThresholdDbm = -65.0;
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate3MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate4_5MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate27MbpsBW10MHz ());
+}
+
+void
+PhySimWifiPhy::Configure80211p_SCH (void)
+{
+ NS_LOG_FUNCTION (this);
+ m_frequency = 5.9e9;
+ SetSymbolTime ( MicroSeconds (8) );
+ m_txCenterFreqTolerance = 20;
+ m_ccaMode1ThresholdDbm = -65.0;
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate3MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate4_5MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate6MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate9MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate12MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate18MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate24MbpsBW10MHz ());
+ m_deviceRateSet.push_back (WifiPhy::GetOfdmRate27MbpsBW10MHz ());
+}
+
+void
+PhySimWifiPhy::ResetRNG ()
+{
+ m_rngReset = false;
+}
+
+void
+PhySimWifiPhy::ClearCache ()
+{
+ m_cachedPreamble.clear ();
+ m_cachedPreamble.set_size (0);
+}
+
+void
+PhySimWifiPhy::StartReceivePacket (Ptr<Packet> packet,
+ Ptr<PhySimWifiPhyTag> tag)
+{
+ NS_LOG_FUNCTION (this << packet << tag );
+
+ // Apply rxAntennaGain
+ itpp::cvec rxedSamples = tag->GetRxedSamples ();
+ if (m_rxGainDb != 0)
+ {
+ rxedSamples *= sqrt (PhySimHelper::DbToRatio (m_rxGainDb));
+ }
+
+ double rxPower = PhySimHelper::RatioToDb (PhySimHelper::GetOFDMSymbolSignalStrength (rxedSamples));
+ NS_LOG_DEBUG ("PhySimWifiPhy:StartReceivePacket() " << Simulator::Now ().GetSeconds () << " sec - current state = " << m_state->GetState ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:StartReceivePacket() " << Simulator::Now ().GetSeconds () << " sec - rxedSamples.size() = " << rxedSamples.size ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:StartReceivePacket() " << Simulator::Now ().GetSeconds () << " sec - first OFDM symbol has signal strength of " << rxPower << " dBm");
+ NS_LOG_DEBUG ("PhySimWifiPhy:StartReceivePacket() " << Simulator::Now ().GetSeconds () << " sec - m_edThresholdDbm = " << m_edThresholdDbm << " dBm");
+ if (rxPower < m_edThresholdDbm)
+ {
+ return;
+ }
+#ifdef NS3_LOG_ENABLE
+ uint32_t blocks = (uint32_t)(std::floor (rxedSamples.size () / 80.0));
+#endif
+ Time rxDuration = CalculateTxDuration ( packet->GetSize (), tag->GetTxWifiMode (), tag->GetWifiPreamble () );
+
+ Time endRx = Simulator::Now () + rxDuration;
+ NS_LOG_DEBUG ( "PhySimWifiPhy:StartReceivePacket() " << Simulator::Now ().GetSeconds () <<
+ " sec - received frame with " << blocks << " OFDM symbols --> rxDuration = " <<
+ rxDuration.GetMicroSeconds () << " microseconds endRx = " << endRx.GetSeconds () << " sec" );
+
+ // Create a packet event and add the packet to the interference helper list
+ Ptr<PhySimInterferenceHelper::Event> event = m_interference->Add (packet, tag);
+
+ switch (m_state->GetState ())
+ {
+
+ case PhySimWifiPhy::SYNCING:
+ case PhySimWifiPhy::TX:
+
+ // Only check for CCA busy condition in SYNC and TX state.
+ CheckForNextCcaBusyStart ();
+ NotifyRxDrop (packet);
+ break;
+
+ case PhySimWifiPhy::RX:
+
+ NS_LOG_DEBUG ("PhySimWifiPhy:StartReceivePacket() " << Simulator::Now ().GetSeconds () <<
+ " sec - drop packet because already in " << m_state->GetState ());
+
+ NotifyRxDrop (packet);
+ break;
+
+ case PhySimWifiPhy::CCA_BUSY:
+ case PhySimWifiPhy::IDLE:
+
+ Time preambleDuration = MicroSeconds ( 4.0 * m_symbolTime.GetMicroSeconds () );
+ NS_LOG_LOGIC ("PhySimWifiPhy:StartReceivePacket() " << Simulator::Now ().GetSeconds () <<
+ " sec - will schedule a new EndSync event " << preambleDuration.GetMicroSeconds () << " microseconds ahead in the future");
+
+ EventId endPreambleEvent = Simulator::Schedule (preambleDuration, &PhySimWifiPhy::EndPreamble, this,
+ packet,
+ tag,
+ event);
+ m_endPreambleEvents.insert ( std::pair<Ptr<PhySimInterferenceHelper::Event>, EventId> (event, endPreambleEvent));
+
+ CheckForNextCcaBusyStart ();
+
+ break;
+ }
+}
+
+void
+PhySimWifiPhy::SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel)
+{
+ NS_LOG_FUNCTION (this << packet << mode << preamble << (uint32_t) txPowerLevel);
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() " << Simulator::Now ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() current state = " << m_state->GetState ());
+
+ // If the requested WiFi mode is not OFDM based, discard the request
+ if (mode.GetModulationClass () != WIFI_MOD_CLASS_OFDM)
+ {
+ return;
+ }
+
+ /* 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 ());
+
+ // Take the seed number from ns3::SeedManager and give it to the global
+ // IT++ random number generator
+ if (!m_rngReset)
+ {
+ itpp::RNG_reset (SeedManager::GetSeed ());
+ m_rngReset = true;
+ }
+
+ // If no data bits are given, then we create a random bit sequence
+ // otherwise, we take the bits that are available via packet->PeekData ()
+ uint32_t length = packet->GetSize ();
+ uint32_t sSizeBefore = packet->GetSerializedSize();
+ uint8_t *payload = (uint8_t*) malloc (packet->GetSize ());
+ memset (payload, 0, packet->GetSize ());
+ packet->CopyData (payload, packet->GetSize ());
+ uint32_t sSizeAfter = packet->GetSerializedSize();
+ itpp::bvec bits;
+
+ if (sSizeBefore == sSizeAfter)
+ { // if there is custom payload provided, we'll use it
+ for (uint32_t i = 0; i < length; i++)
+ {
+ uint8_t byte = payload[i];
+ bits.ins (bits.size (), PhySimHelper::DecToBin (byte, 8));
+ }
+ }
+ else
+ { // else we create a random bit sequence
+ bits = itpp::randb (length*8);
+ }
+ free (payload);
+
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() - packet->GetSize() = " << length << " bytes & bits.length() = " << bits.length ());
+ NS_ASSERT (length >= 1 && length <= 4095); // MSPDU must adhere to these (Table 17-15 in Std.)
+
+ // use cached preamble if existing
+ if (m_cachedPreamble.size () < 320)
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() - constructing preamble");
+ m_cachedPreamble = ConstructPreamble ();
+ }
+
+ itpp::cvec c_header = ConstructSignalHeader (bits.length (), mode);
+ itpp::cvec c_data = ConstructData (bits, mode);
+
+ // compose final result
+ itpp::cvec endresult = itpp::cvec (m_cachedPreamble);
+ // add overlap of header with preamble
+ endresult (endresult.size () - 1) += c_header (0);
+ // add rest of header
+ endresult.ins (endresult.size (), c_header (1, c_header.size () - 1));
+ // add overlap of header with first DATA
+ endresult (endresult.size () - 1) += c_data (0);
+ // add rest of data
+ endresult.ins (endresult.size (), c_data (1, c_data.size () - 1));
+
+ // If we want to normalize the power of each OFDM symbol block
+ if (m_normalizeOfdmBlocks)
+ {
+ endresult *= m_normFactor;
+ }
+
+ // Apply Transmission Power amplification and Antenna gain
+ double txPowerDbm = PhySimHelper::GetPowerDbm (txPowerLevel, m_nTxPower, m_txPowerBaseDbm, m_txPowerEndDbm);
+ endresult *= sqrt ( PhySimHelper::DbToRatio (txPowerDbm + m_txGainDb) );
+
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() txPowerDbm = " << txPowerDbm);
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() txAntGain = " << m_txGainDb);
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() applied a transmit power amplification factor of " << sqrt ( PhySimHelper::DbToRatio (txPowerDbm + m_txGainDb) ));
+
+ // Cancel all running end(Preamble|Header|RX) events
+ CancelAllRunningEndPreambleEvents ();
+ CancelAllRunningEndHeaderEvents ();
+ if (m_endRxEvent.IsRunning ())
+ {
+ m_endRxEvent.Cancel ();
+ }
+ NotifyTxBegin (packet);
+
+ uint32_t dataRate500KbpsUnits = mode.GetDataRate () / 500000;
+ bool isShortPreamble = (WIFI_PREAMBLE_SHORT == preamble);
+ // TODO: Update call below once multi-channel operation is supported
+ NotifyPromiscSniffTx (packet, (uint16_t) m_frequency, 0, dataRate500KbpsUnits, isShortPreamble);
+ Time txDuration = CalculateTxDuration (packet->GetSize (), mode, preamble);
+
+ // Apply oscillator effect of transmitter/receiver --this accounts for both
+ int32_t phaseOffset;
+ if (m_fixedPhaseOffset > 0)
+ {
+ phaseOffset = m_fixedPhaseOffset;
+ }
+ else
+ {
+ phaseOffset = (m_txCenterFreqTolerance != 0
+ ? itpp::randi (-2 * m_txCenterFreqTolerance, 2 * m_txCenterFreqTolerance)
+ : 0);
+ }
+
+ // Frequency offset tolerance is 10ppm for 5 MHz channel in 802.11 or 10 MHz vehicular; it is 20 for
+ // 10 MHz and 20 MHz 802.11 transceivers (non-p). The offset is exp(j*2pi*Df*Ts*i), where Df=errorInPpm*Fc
+ // In 802.11p, look up 17.3.9.4
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() - phaseOffset = " << phaseOffset << " (m_txCenterFreqTolerance = " << m_txCenterFreqTolerance << ")");
+ double Df = phaseOffset * (1e-6) * m_frequency;
+ double phaseFactor = 2.0 * M_PI * Df * m_sampleTime;
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() - phaseFactor = " << phaseFactor);
+
+ itpp::cvec oscillatedOutput (endresult.size ());
+ if (phaseFactor != 0)
+ {
+ for (int32_t i = 0; i < oscillatedOutput.size (); ++i)
+ {
+ oscillatedOutput (i) = endresult (i) * std::complex<double> (cos (phaseFactor * (i + 1)), sin (phaseFactor * (i + 1)));
+ }
+ }
+ else
+ {
+ oscillatedOutput = endresult;
+ }
+ // Create PhySimWifiPhyTag, fill its attributes and send packet over the channel
+ Ptr<PhySimWifiPhyTag> phyTag = Create<PhySimWifiPhyTag> ();
+ phyTag->SetTxParameters (preamble, mode, txDuration, bits, endresult, m_frequency, m_sampleTime, m_device->GetObject<NetDevice> ());
+ phyTag->SetTxPower (txPowerDbm);
+
+ // Set the default RX samples to the one after oscillation effects have
+ // been applied.
+ phyTag->SetRxSamples (oscillatedOutput);
+
+ m_state->SwitchToTx (txDuration, packet, phyTag);
+ m_txTrace (packet, phyTag);
+
+ NS_LOG_LOGIC ("PhySimWifiPhy:SendPacket() transmit packet " << packet->GetUid () << " with size of " << (8 * packet->GetSize ()) << " bits");
+ NS_LOG_INFO ("PhySimWifiPhy:SendPacket() transmit duration: " << txDuration.GetMicroSeconds () << " microseconds");
+ NS_LOG_DEBUG ("PhySimWifiPhy:SendPacket() samples consist of " << phyTag->GetTxedSamples ().size () << " samples");
+
+ m_channel->Send (this, packet, phyTag);
+}
+
+itpp::cvec
+PhySimWifiPhy::ConstructPreamble ()
+{
+ // OFDM the short symbol
+ itpp::cvec ofdmShortSymbol = m_ofdmSymbolCreator->Modulate (m_shortSymbol);
+
+ // Create the ShortSymbolSequence (This is twice the ofdmShortSymbol and the next 33 elements)
+ itpp::cvec ofdmShortSymbolSequence (ofdmShortSymbol);
+ ofdmShortSymbolSequence.ins (ofdmShortSymbolSequence.size (), ofdmShortSymbol);
+ ofdmShortSymbolSequence.ins (ofdmShortSymbolSequence.size (), ofdmShortSymbol.mid (0, 33));
+ PhySimHelper::WindowFunction (ofdmShortSymbolSequence); // apply window function
+
+ // The following constructs the long training symbol sequence
+ itpp::cvec ofdmFirstLongSymbol = m_ofdmSymbolCreator->Modulate (m_longSymbol, 32);
+ itpp::cvec ofdmLongSymbolSequence (ofdmFirstLongSymbol);
+ ofdmLongSymbolSequence.ins (ofdmLongSymbolSequence.size (), ofdmFirstLongSymbol.mid (32, 64));
+
+ // The last element is a repetition of the first sample of the non-cp part of the OFDM symbol
+ ofdmLongSymbolSequence.ins (ofdmLongSymbolSequence.size (), ofdmFirstLongSymbol (32));
+ PhySimHelper::WindowFunction (ofdmLongSymbolSequence);
+
+ // Construct the final preamble
+ itpp::cvec preambleSequence (321);
+ preambleSequence.replace_mid (0, ofdmShortSymbolSequence);
+ preambleSequence (160) += ofdmLongSymbolSequence (0); // the overlap
+ preambleSequence.replace_mid (161, ofdmLongSymbolSequence (1, 160));
+
+ return preambleSequence;
+}
+
+itpp::cvec
+PhySimWifiPhy::ConstructSignalHeader (uint32_t length, const WifiMode mode)
+{
+ NS_ASSERT ( length % 8 == 0 && length <= 4095 * 8 && length >= 8); // MSPDU restrictions (Table 17-15 in Std)
+
+ // Signal header is always modulated with BPSK and 1/2 coding rate
+ m_ofdmSymbolCreator->SetModulationType (PhySimHelper::BPSK, 2);
+ m_convEncoder->SetCodingRate (WIFI_CODE_RATE_1_2);
+
+ // Construct header
+ int hdr_len = length / 8; // turn to bytes
+ itpp::bvec PLCP_Header (24); // place the header here
+ PLCP_Header.zeros ();
+
+ // Add the rate bits
+ PLCP_Header.replace_mid (0, PhySimHelper::CreateRateField (mode)); // position 0..3
+ PLCP_Header (4) = 0; // reserved bit
+ itpp::bvec length_bits = PhySimHelper::DecToBin (hdr_len, 12);
+ PLCP_Header.replace_mid (5, length_bits); // length bits, position 5..16
+ PLCP_Header (17) = PhySimHelper::CalcEvenParity (PLCP_Header); // add parity bit
+
+ // Do convolutional encoding
+ itpp::bvec encoded = m_convEncoder->Encode (PLCP_Header);
+
+ // Do interleaving
+ m_interleaver->SetWifiMode (WifiPhy::GetOfdmRate6Mbps ());
+ itpp::bvec interleavedHeader = m_interleaver->InterleaveBlock (encoded);
+ itpp::cvec modulated = (m_ofdmSymbolCreator->Modulate (interleavedHeader, 0));
+
+ // Also add another sample which will overlap with the first DATA symbol
+ modulated.ins (modulated.size (), modulated (16));
+
+ // Apply window function
+ PhySimHelper::WindowFunction (modulated);
+
+ return modulated;
+}
+
+itpp::cvec
+PhySimWifiPhy::ConstructData (const itpp::bvec& bits, const WifiMode mode)
+{
+ itpp::bvec serviceField (16);
+ serviceField.zeros (); // 16-bit all zero service field
+ itpp::bvec tailField (6);
+ tailField.zeros (); // 6-bit zero tail field
+
+ // Calculate no. of symbols needed and creating padding
+ // Note that in the calculations below we use bits.length rather than 8 * length (in bytes)
+ uint32_t NDBPS = PhySimHelper::GetNDBPS (mode); // No. of data bits per symbol
+ uint32_t NSYM = ceil (static_cast<double> (16 + bits.length () + 6) / static_cast<double> (NDBPS)); // 17-11
+ uint32_t NDATA = NSYM * NDBPS; // 17-12 - length of data field
+ uint32_t NPAD = NDATA - (16 + bits.length () + 6); // no. of pad bits needed
+
+ // Create the data bits (SERVICE+PSDU+Tail+Pad)
+ itpp::bvec dataBits (NDATA);
+ dataBits.zeros ();
+ dataBits.replace_mid (0, serviceField); // 0..15 service field
+ dataBits.replace_mid (16, bits); // 16..16+bits.length()-1 the bits
+ dataBits.replace_mid (16 + bits.length (), tailField);
+
+ // 17.3.5.4 apply PLCP scrambler
+ itpp::bvec scrambledDATA = m_scrambler->Scramble (dataBits);
+
+ // 17.3.2.1 (f) After scrambling we have to reset the tail bits to 0
+ for (int i = 0; i < 6; ++i)
+ {
+ scrambledDATA (scrambledDATA.size () - 1 - NPAD - i) = 0;
+ }
+
+ // 17.3.5.5 Do convolutional encoding
+ m_convEncoder->SetCodingRate (mode.GetCodeRate ());
+ itpp::bvec encodedScrambledDATA = m_convEncoder->Encode (scrambledDATA);
+
+ // 17.3.5.6 Do interleaving and 17.3.5.7 - 17.3.5.9 OFDM
+ // for each block -- return the result
+ m_interleaver->SetWifiMode (mode);
+ itpp::cvec modulated = InterleaveAndModulate (encodedScrambledDATA, mode);
+
+ return modulated;
+}
+
+itpp::bvec
+PhySimWifiPhy::DeconstructData (Ptr<Packet> packet, Ptr<PhySimWifiPhyTag> tag)
+{
+ NS_LOG_FUNCTION (this << packet << tag);
+
+ // read reception wifi mode and PDU length in bytes
+ WifiMode mode = tag->GetRxWifiMode ();
+ uint32_t length = 8 * tag->GetLength ();
+
+ uint32_t tailNservice = 22; // service field (16 bits) plus tail bits (6 bits)
+ uint32_t ndbps = PhySimHelper::GetNDBPS (mode);
+ uint32_t padding = ndbps - (tailNservice + length) % (ndbps);
+ uint32_t numSymbols = ceil ( (tailNservice + length + padding) / ndbps); // see Equation 17-11
+
+ NS_LOG_DEBUG ("PhySimWifiPhy:DeconstructData() rxWifiMode: " << tag->GetRxWifiMode ().GetUniqueName ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:DeconstructData() numSybmols: " << numSymbols);
+ NS_LOG_DEBUG ("PhySimWifiPhy:DeconstructData() numDataBitsPerSymbol: " << ndbps);
+ NS_LOG_DEBUG ("PhySimWifiPhy:DeconstructData() length: " << length);
+
+ // Apply offset estimate correction from training sequence
+ // For now: take the data stream and decode it
+ Time now = Simulator::Now ();
+ Time start = now - NanoSeconds (m_symbolTime.GetNanoSeconds () * numSymbols);
+ NS_LOG_DEBUG ("PhySimWifiPhy:DeconstructData() calling m_interference->GetCumulativeSamples(" << start << "," << now << ")");
+ itpp::cvec samples = m_interference->GetCumulativeSamples (start, now);
+ double estimate = tag->GetInitialEstimate ();
+ itpp::cvec Data = m_estimator->ApplyEstimateFromTrainingSequence (samples, estimate, 1);
+
+ // De-Interleave and demodulate (we are NOT in the signal header anymore)
+ itpp::vec encodedScrambledData = DeinterleaveAndModulate (Data, mode);
+ NS_LOG_DEBUG ("PhySimWifiPhy:DeconstructData() encodedScrambledData.size(): " << encodedScrambledData.size () << " bits");
+
+ // Do Viterbi decoding
+ m_convEncoder->SetCodingRate (mode.GetCodeRate ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:DeconstructData() called m_convEncoder->SetCodingRate(" << mode.GetCodeRate () << ")");
+ itpp::bvec scrambledData = m_convEncoder->Decode (encodedScrambledData);
+
+ // Descramble
+ itpp::bvec initialState = scrambledData (0, 6); // read the scrambling sequence from decoded DATA
+ itpp::bvec DATA = m_scrambler->DeScramble ( scrambledData ( 7, scrambledData.size () - 1 ), initialState );
+
+ // Calculate no. of symbols needed
+ uint32_t nDATA = numSymbols * ndbps; // Equation 17-12 - length of data field
+ itpp::bvec finalData = DATA (16, nDATA - padding - 6 - 1);
+
+ return finalData;
+}
+
+itpp::cvec
+PhySimWifiPhy::InterleaveAndModulate (const itpp::bvec &encodedScrambledData, const WifiMode mode)
+{
+ uint32_t NCBPS = PhySimHelper::GetNCBPS (mode);
+ m_interleaver->SetWifiMode (mode);
+ m_ofdmSymbolCreator->SetModulationType (PhySimHelper::GetModulationType (mode), mode.GetConstellationSize ());
+
+ int32_t startIndex = 0;
+ int32_t endIndex = NCBPS - 1;
+ int32_t blockIndex = 0;
+ itpp::cvec finalModulatedData;
+ itpp::cvec block;
+
+ while ( endIndex < encodedScrambledData.size () )
+ {
+ blockIndex++; // Next block
+
+ // Interleave and modulate the block. Then apply the window function
+ block = InterleaveAndModulateBlock (encodedScrambledData (startIndex, endIndex), blockIndex);
+
+ // Need to add the first element of the actual OFDM time sample (not the prefix)
+ // at the end. This will be added as an overlap with the next time sample
+ std::complex<double> (lastelement) = block (16);
+ block.ins (block.size (), lastelement);
+
+ // Windowing function for block
+ PhySimHelper::WindowFunction (block);
+
+ // Consider the block overlap
+ if (blockIndex == 1)
+ { // First block just add...
+ finalModulatedData.ins (finalModulatedData.size (), block);
+ }
+ else
+ {
+ // Overlap block with Data
+ finalModulatedData (finalModulatedData.size () - 1) += block (0);
+ finalModulatedData.ins (finalModulatedData.size (), block (1, block.size () - 1));
+ }
+ startIndex += NCBPS;
+ endIndex += NCBPS;
+ }
+
+ return finalModulatedData;
+}
+
+itpp::cvec
+PhySimWifiPhy::InterleaveAndModulateBlock (const itpp::bvec& input, const uint32_t index)
+{
+ NS_ASSERT ( index > 0 );
+ itpp::bvec interleaved = m_interleaver->InterleaveBlock (input);
+ itpp::cvec modulated = m_ofdmSymbolCreator->Modulate (interleaved, index);
+
+ return modulated;
+}
+
+itpp::vec
+PhySimWifiPhy::DeinterleaveAndModulate (const itpp::cvec &input, const WifiMode mode)
+{
+ NS_ASSERT ( input.size () % 80 == 0 );
+
+ m_interleaver->SetWifiMode (mode);
+ m_ofdmSymbolCreator->SetModulationType (PhySimHelper::GetModulationType (mode), mode.GetConstellationSize ());
+
+ // There are 80 time samples per OFDM symbol
+ const uint32_t sampleSize = 80;
+ int32_t startIndex = 0;
+ int32_t endIndex = sampleSize - 1;
+ int32_t blockIndex = 0;
+ itpp::vec finalDecodedData;
+ itpp::vec block;
+
+ while (endIndex < input.size ())
+ {
+ blockIndex++; // next block
+ block = DeinterleaveAndModulateBlock ( input (startIndex, endIndex), blockIndex );
+ finalDecodedData.ins ( finalDecodedData.size (), block );
+ startIndex += sampleSize;
+ endIndex += sampleSize;
+ }
+
+ return finalDecodedData;
+}
+
+itpp::vec
+PhySimWifiPhy::DeinterleaveAndModulateBlock (const itpp::cvec& input, uint32_t symbolNo)
+{
+ itpp::vec demodulated = m_ofdmSymbolCreator->DeModulate (input, symbolNo);
+ return m_interleaver->DeinterleaveBlock (demodulated);
+}
+
+void
+PhySimWifiPhy::EndPreamble (Ptr<Packet> packet, Ptr<PhySimWifiPhyTag> tag, Ptr<PhySimInterferenceHelper::Event> event)
+{
+ NS_LOG_FUNCTION (this << packet << tag << event);
+
+ Time now = Simulator::Now ();
+ // deviation time which is added around the exact preamble when getting cumulative samples
+ Time devTime = MicroSeconds (2);
+ uint64_t sampleDuration = m_symbolTime.GetNanoSeconds () / 80.0;
+ uint32_t devSamples = (devTime.GetNanoSeconds () / sampleDuration);
+ // get cumulative samples
+ Time pre = NanoSeconds (4 * m_symbolTime.GetNanoSeconds ());
+ itpp::cvec samples = m_interference->GetCumulativeSamples (now - pre - devTime, now + devTime);
+ int32_t beginShortSymbols = -1;
+
+ double sinr = m_interference->CalculatePreambleSinr (event);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() preamble of packet " << packet->GetUid () << " has SINR of " << sinr);
+ tag->SetPreambleSinr (sinr);
+
+ // Continue with reception if the preamble was detected successfully
+ // or if we perform BER calculations only
+ if ( (sinr > 0.0) && m_signalDetector->ScanPreamble (packet, tag, samples, beginShortSymbols)
+ && (m_state->IsStateCcaBusy () || m_state->IsStateIdle () || !m_state->IsStateSync ()))
+ {
+ NS_ASSERT (beginShortSymbols >= 0);
+ int32_t beginLongSymbols = m_signalDetector->ScanForLongSeq (packet, tag, samples (beginShortSymbols, samples.size () - 1));
+ int32_t endShortSymbols = beginLongSymbols + beginShortSymbols - 32;
+ beginLongSymbols = endShortSymbols + 1;
+ beginShortSymbols = beginLongSymbols - 160;
+
+ // add correction because we use it later without the deviation around the preamble
+ tag->SetLongSymbolStart (beginLongSymbols - devSamples);
+
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() preamble detected successfully");
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() -> beginShortSymbols = " << beginShortSymbols);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() -> endShortSymbols = " << endShortSymbols);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() -> beginLongSymbols = " << beginLongSymbols);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() -> devSamples = " << devSamples);
+
+ // Check whether we have "valid" begin/end samples for the long/short symbols
+ // if not, discard this packet. Note: this should never happen, since the thresholds
+ // of the signal detector should avoid such a situation before getting here
+ if (beginShortSymbols < 0 || (beginLongSymbols + 160 > samples.size ()))
+ {
+ double sinr = m_interference->CalculatePreambleSinr (event);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() discarding packet, due to invalid start/end times for the preamble symbols");
+ tag->SetPreambleSinr (sinr);
+ m_preambleErrorTrace (packet, tag);
+ goto EndPreambleWrapUp;
+ }
+
+ // estimate coarse and fine channel offsets
+ m_estimator->Reset ();
+ double offset = m_estimator->GetInitialChannelEstimation ( samples (beginShortSymbols, beginLongSymbols + 160 - 1) );
+ tag->SetInitialEstimate (offset);
+
+ // schedule a new EndHeader event and switch to SYNCING state
+ Time headerDuration = m_symbolTime;
+ NS_LOG_LOGIC ("PhySimWifiPhy:EndPreamble() -> scheduling new event for endHeader " << headerDuration.GetMicroSeconds () << " microseconds ahead in the future.");
+ EventId endHeaderEvent = Simulator::Schedule (headerDuration, &PhySimWifiPhy::EndHeader, this,
+ packet,
+ tag,
+ event);
+ m_endHeaderEvents.insert ( std::pair<Ptr<PhySimInterferenceHelper::Event>, EventId> (event, endHeaderEvent));
+
+ m_state->SwitchToSync (headerDuration, packet, tag);
+ m_preambleOkTrace (packet, tag);
+ }
+ else
+ {
+ m_preambleErrorTrace (packet, tag);
+
+ // If we want to know the overall average SINR of this frame later
+ if (m_calculateOverallSinr)
+ {
+ double sinr = m_interference->CalculateOverallSinr (event);
+ tag->SetOverallSinr (sinr);
+ }
+ }
+
+EndPreambleWrapUp:
+ // Don't forget to delete this event from the list of endPreamble events
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() erasing endPreamble event from list, liste.size() = " << m_endPreambleEvents.size ());
+ m_endPreambleEvents.erase (event);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndPreamble() now, liste.size() = " << m_endPreambleEvents.size ());
+}
+
+void
+PhySimWifiPhy::EndHeader (Ptr<Packet> packet, Ptr<PhySimWifiPhyTag> tag, Ptr<PhySimInterferenceHelper::Event> event)
+{
+ NS_LOG_FUNCTION (this << packet << tag << event);
+
+ Time now = Simulator::Now ();
+ itpp::cvec samples = m_interference->GetCumulativeSamples (now - m_symbolTime, now);
+
+ // next, apply offset estimation correction which was obtained from the training sequence
+ double estimate = tag->GetInitialEstimate ();
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() applying estimate from training symbols: " << estimate);
+ itpp::cvec Signal = m_estimator->ApplyEstimateFromTrainingSequence (samples, estimate, 0);
+
+ // Save information about SINR of the header part
+ if (m_calculateHeaderSinr)
+ {
+ double sinr = m_interference->CalculateHeaderSinr (event);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() signal header of packet " << packet->GetUid () << " has SINR of " << sinr);
+ tag->SetHeaderSinr (sinr);
+ }
+
+ // Continue with reception if the signal header was decoded successfully
+ if ( ScanSignalField (tag, Signal) && (m_state->IsStateCcaBusy () || m_state->IsStateIdle () || m_state->IsStateSync ()) )
+ {
+
+ WifiMode mode = tag->GetRxWifiMode ();
+ uint32_t length = 8 * tag->GetLength (); // transform to bits
+
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() successfully decoded signal header:");
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() -> detected wifiMode: " << mode.GetUniqueName ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() -> should be wifiMode: " << tag->GetTxWifiMode ().GetUniqueName ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() -> detected length: " << length << " bits");
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() -> should be length: " << (8 * packet->GetSize ()) << " bits");
+
+ uint32_t tailNservice = 22; // service field (16 bits) plus tail bits (6 bits)
+ uint32_t ndbps = PhySimHelper::GetNDBPS (mode);
+ uint32_t padding = ndbps - (tailNservice + length) % (ndbps);
+
+ // number of data symbols times symbol time
+ uint64_t delay = m_symbolTime.GetMicroSeconds () *
+ ceil ( (length + tailNservice + padding) / ndbps );
+
+ Time payloadDuration = MicroSeconds (delay);
+ m_endRxEvent = Simulator::Schedule (payloadDuration, &PhySimWifiPhy::EndRx, this,
+ packet,
+ tag,
+ event);
+ NS_LOG_LOGIC ("PhySimWifiPhy:EndHeader() signal header decoded successfully -> scheduled new event " <<
+ payloadDuration.GetMicroSeconds () << " microseconds ahead in the future.");
+
+ m_state->SwitchFromSyncEndOk (packet, tag);
+ m_headerOkTrace (packet, tag);
+ m_state->SwitchToRx (payloadDuration);
+
+ // If we go into RX state, we should cancel all running EndPreamble and EndHeader events, since
+ // we have no frame capture support yet
+ CancelAllRunningEndPreambleEvents ();
+ CancelAllRunningEndHeaderEvents ();
+
+ // If we are going into RX state, we can safely cancel all CCA busy events that are scheduled
+ // Why? Because we will check the CCA condition again after EndRx()
+ m_startCcaBusyEvent.Cancel ();
+ m_endCcaBusyEvent.Cancel ();
+ }
+ else
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndHeader() signal header NOT decoded successfully");
+ m_state->SwitchFromSyncEndError (packet, tag);
+ m_headerErrorTrace (packet, tag);
+
+ // If we want to know the overall average SINR of this frame later
+ if (m_calculateOverallSinr)
+ {
+ double sinr = m_interference->CalculateOverallSinr (event);
+ tag->SetOverallSinr (sinr);
+ }
+ }
+}
+
+void
+PhySimWifiPhy::EndRx (Ptr<Packet> packet, Ptr<PhySimWifiPhyTag> tag, Ptr<PhySimInterferenceHelper::Event> event)
+{
+
+ NS_LOG_FUNCTION (this << packet << tag << event);
+ itpp::bvec finalData = DeconstructData (packet, tag);
+ tag->SetRxDataBits (finalData);
+
+#ifdef NS3_LOG_ENABLE
+ uint32_t bytes = finalData.size () / 8;
+ std::string rxPayload;
+ for (uint32_t i = 0; i < bytes; i++)
+ {
+ itpp::bvec extract = finalData ((i * 8), (i * 8) + 8 - 1);
+ const char c = itpp::bin2dec ( extract, false );
+ rxPayload.append (&c);
+ }
+ NS_LOG_INFO ("PhySimWifiPhy:EndRx() received " << finalData.size () << " data bits: " << finalData);
+ NS_LOG_INFO ("PhySimWifiPhy:EndRx() message: " << rxPayload);
+#endif
+
+ // Save information about the average SINR of the data part
+ if (m_calculatePayloadSinr)
+ {
+ double sinr = m_interference->CalculatePayloadSinr (event);
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndRx() payload of packet " << packet->GetUid () << " has SINR of " << sinr);
+ tag->SetPayloadSinr (sinr);
+ }
+ // If we want to know the overall average SINR of this frame later
+ if (m_calculateOverallSinr)
+ {
+ double sinr = m_interference->CalculateOverallSinr (event);
+ tag->SetOverallSinr (sinr);
+ }
+
+ if ( finalData == tag->GetTxedDataBits () )
+ {
+ NS_LOG_LOGIC ("PhySimWifiPhy:EndRx() payload of packet " << packet->GetUid () << " decoded successfully");
+ m_state->SwitchFromRxEndOk (packet, tag);
+ uint32_t dataRate500KbpsUnits = tag->GetRxWifiMode ().GetDataRate () / 500000;
+ bool isShortPreamble = (WIFI_PREAMBLE_SHORT == tag->GetWifiPreamble ());
+ // TODO: Update call below to provide proper signal energy levels and noise levels
+ // TODO: Update the call below once multi-channel operations is supported
+ NotifyPromiscSniffRx (packet, (uint16_t) m_frequency, 0, dataRate500KbpsUnits, isShortPreamble, -1.0, -1.0);
+ m_rxOkTrace (packet, tag);
+ }
+ else
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:EndRx() payload of packet " << packet->GetUid () << " not decoded successful");
+ m_state->SwitchFromRxEndError (packet, tag);
+ m_rxErrorTrace (packet, tag);
+ }
+
+ // Ok, we have finished a reception, so we have to make sure we track the
+ // CCA busy status appropriately
+ CheckForNextCcaBusyStart ();
+}
+
+bool
+PhySimWifiPhy::ScanSignalField (Ptr<PhySimWifiPhyTag> tag, const itpp::cvec &input)
+{
+ NS_ASSERT (input.size () == 80);
+
+ // Demodulate
+ m_ofdmSymbolCreator->SetModulationType (PhySimHelper::BPSK, 2);
+ itpp::vec demodulated = (m_ofdmSymbolCreator->DeModulate (input, true));
+
+ // De-Interleave
+ m_interleaver->SetWifiMode (WifiPhy::GetOfdmRate6Mbps ());
+ itpp::vec deInterleavedHeader = m_interleaver->DeinterleaveBlock (demodulated);
+
+ // Viterbi-Decode
+ m_convEncoder->SetCodingRate (WIFI_CODE_RATE_1_2);
+ itpp::bvec decoded = m_convEncoder->Decode (deInterleavedHeader);
+
+ // if parity bit is o.k.
+ if (PhySimHelper::CheckSignalField (decoded))
+ {
+ // read rate field, if unsupported rate, cancel here already
+ WifiMode mode;
+ if (!PhySimHelper::GetWifiMode (decoded (0, 3), mode))
+ {
+ return false;
+ }
+ tag->SetRxWifiMode (mode);
+
+ if (!(mode == tag->GetRxWifiMode ()))
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:ScanSignalField() returning false because detected wifiMode != transmitted wifiMode");
+ return false;
+ }
+
+ // read length and apply plausibility check
+ NS_LOG_DEBUG ("PhySimWifiPhy:ScanSignalField() lengthField = " << decoded (5, 16));
+ uint32_t length = itpp::bin2dec ( decoded (5, 16), false );
+ NS_LOG_DEBUG ("PhySimWifiPhy:ScanSignalField() --> length = " << length);
+ tag->SetLength (length);
+ if (length < 1 || length > 4095)
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:ScanSignalField() returning false because length field failed plausibility check");
+ return false; // make sure the length makes sense 17.2.3.1
+ }
+ if (!(length == tag->GetLength ()))
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:ScanSignalField() returning false because detected frame length != correct frame length");
+ return false;
+ }
+
+ return true;
+ }
+ NS_LOG_DEBUG ("PhySimWifiPhy:ScanSignalField() returning false because CheckSignalField() failed");
+ return false;
+}
+
+void
+PhySimWifiPhy::CancelAllRunningEndPreambleEvents ()
+{
+ if (!m_endPreambleEvents.empty ())
+ {
+ std::map<Ptr<PhySimInterferenceHelper::Event>, EventId>::iterator it;
+ for (it = m_endPreambleEvents.begin (); it != m_endPreambleEvents.end (); it++)
+ {
+ if (it->second.IsRunning ())
+ {
+ it->second.Cancel ();
+ }
+ }
+ m_endPreambleEvents.clear ();
+ NS_LOG_DEBUG ("PhySimWifiPhy::CancelAllRunningEndPreambleEvents() - canceled all running endPreambleEvents. list.size() = " << m_endPreambleEvents.size ());
+ }
+}
+
+void
+PhySimWifiPhy::CancelAllRunningEndHeaderEvents ()
+{
+ if (!m_endHeaderEvents.empty ())
+ {
+ std::map<Ptr<PhySimInterferenceHelper::Event>, EventId>::iterator it;
+ for (it = m_endHeaderEvents.begin (); it != m_endHeaderEvents.end (); it++)
+ {
+ if (it->second.IsRunning ())
+ {
+ it->second.Cancel ();
+ }
+ }
+ m_endHeaderEvents.clear ();
+ NS_LOG_DEBUG ("PhySimWifiPhy::CancelAllRunningEndHeaderEvents() - canceled all running endHeaderEvents. list.size() = " << m_endHeaderEvents.size ());
+ }
+}
+
+void
+PhySimWifiPhy::CheckForNextCcaBusyStart ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ if (m_endCcaBusyEvent.IsRunning ())
+ {
+ return;
+ }
+
+ Time delayUntilCcaStart = MicroSeconds (0);
+
+ if (m_interference->IsEnergyReached (m_ccaMode1ThresholdDbm, delayUntilCcaStart))
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() - Yes! Energy raises above " << m_ccaMode1ThresholdDbm << " dBm");
+ // If the next CCA busy phase is starting already right now, skip
+ // the scheduling of a start event and go directly to StartCcaBusy
+ if (delayUntilCcaStart.IsZero ())
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() - it starts immediately.");
+ StartCcaBusy ();
+ }
+ else
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() - its starts in the future, after " << delayUntilCcaStart);
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() -> Simulator::Now() = " << Simulator::Now ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() -> m_endCcaBusyEvent.IsRunning() = " << m_endCcaBusyEvent.IsRunning ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() -> m_endCcaBusyEvent.IsExpired() = " << m_endCcaBusyEvent.IsExpired ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() -> m_endCcaBusyEvent.GetTs() = " << m_endCcaBusyEvent.GetTs ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() -> m_startCcaBusyEvent.IsRunning() = " << m_startCcaBusyEvent.IsRunning ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() -> m_startCcaBusyEvent.IsExpired() = " << m_startCcaBusyEvent.IsExpired ());
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() -> m_startCcaBusyEvent.GetTs() = " << m_startCcaBusyEvent.GetTs ());
+
+ // Make sure no other events are running
+ NS_ASSERT (m_endCcaBusyEvent.IsExpired ());
+ // Think about this here again. Can this really happen?
+ // Explanation: it can happen that a new CCA start phase is detected, and due to
+ // a new incoming frame, the CCA threshold is hit already at an earlier stage
+ Time absoluteTime = delayUntilCcaStart + Simulator::Now ();
+ if (m_startCcaBusyEvent.IsRunning () && (m_startCcaBusyEvent.GetTs () > static_cast<uint64_t> (absoluteTime.GetNanoSeconds ())) )
+ {
+ // Cancel the running event...
+ m_startCcaBusyEvent.Cancel ();
+
+ // ... and schedule a new event at the new starting time
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() - canceling old event, scheduling new m_startCcaBusyEvent at time = " << absoluteTime);
+ m_startCcaBusyEvent = Simulator::Schedule (delayUntilCcaStart, &PhySimWifiPhy::StartCcaBusy, this);
+ }
+ else if (m_startCcaBusyEvent.IsRunning () && (m_startCcaBusyEvent.GetTs () <= static_cast<uint64_t> (absoluteTime.GetNanoSeconds ())) )
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() - now new event scheduled, since there's already an event scheduled.");
+ }
+ else
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() - scheduling m_startCcaBusyEvent at time = " << absoluteTime);
+ m_startCcaBusyEvent = Simulator::Schedule (delayUntilCcaStart, &PhySimWifiPhy::StartCcaBusy, this);
+ }
+ }
+ }
+ else
+ {
+ NS_LOG_DEBUG ("PhySimWifiPhy:CheckForNextCcaBusyStart() - CCA busy threshold will not be reached in the future.");
+ }
+}
+
+/**
+ * Handles the start of a new CCA busy phase, as defined in the IEEE 802.11 2007 standard in Section 17.3.10.5.
+ * It will calculate the duration of the state, schedule an event for the end of the CCA busy phase and instruct
+ * the physical layer state helper (PhySimWifiStateHelper) to switch to CCA busy.
+ */
+void
+PhySimWifiPhy::StartCcaBusy ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ // Do nothing if we are already in CCA busy and simply wait until the end
+ // of the phase has been reached
+ if (m_endCcaBusyEvent.IsRunning ())
+ {
+ NS_LOG_LOGIC ("PhySimWifiPhy:StartCcaBusy() - doing nothing since we are already CCA busy and endCcaBusyEvent is already scheduled");
+ return;
+ }
+
+ Time delayUntilCcaEnd = m_interference->GetEnergyDuration (m_ccaMode1ThresholdDbm);
+
+ NS_LOG_FUNCTION ("PhySimWifiPhy:StartCcaBusy() - We will be busy for " << delayUntilCcaEnd);
+
+ // Continue only if we will be busy in the future
+ if (!delayUntilCcaEnd.IsZero ())
+ {
+ NS_LOG_FUNCTION ("PhySimWifiPhy:StartCcaBusy() - will call m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);");
+ m_state->SwitchMaybeToCcaBusy (delayUntilCcaEnd);
+ m_ccaBusyStartTrace (m_device->GetObject<NetDevice> (), delayUntilCcaEnd);
+
+ // Check if there is already an event for the end of CCA busy scheduled or not
+ if (m_endCcaBusyEvent.IsRunning ())
+ {
+ m_endCcaBusyEvent.Cancel ();
+ }
+
+ // Schedule event at the end of the CCA busy phase
+ NS_LOG_FUNCTION ("PhySimWifiPhy:StartCcaBusy() - scheduling endCcaBusy event after " << delayUntilCcaEnd);
+ m_endCcaBusyEvent = Simulator::Schedule (delayUntilCcaEnd, &PhySimWifiPhy::EndCcaBusy, this);
+ }
+ else
+ {
+ NS_LOG_FUNCTION ("PhySimWifiPhy:StartCcaBusy() - skipping busy phase, since delayUntilIdle = 0");
+ }
+
+ // Make sure that this event is canceled
+ m_startCcaBusyEvent.Cancel ();
+}
+
+/**
+ * Handles the end of a previously started CCA busy phase. In here, we will check when we have to switch
+ * to CCA busy again (maybe the next start of a CCA busy phase is in the future due to fading), which could be
+ * immediately or later. We also should make sure that m_endCcaBusyEvent and m_startCcaBusyEvent are not running
+ * at this point in time.
+ */
+void
+PhySimWifiPhy::EndCcaBusy ()
+{
+ NS_LOG_FUNCTION (this << Simulator::Now ());
+
+ NS_ASSERT (m_endCcaBusyEvent.IsExpired ());
+ NS_ASSERT (m_startCcaBusyEvent.IsExpired ());
+
+ // Proceed only if we are in a state where we have to take care
+ if (m_state->GetState () == PhySimWifiPhy::CCA_BUSY
+ || m_state->GetState () == PhySimWifiPhy::IDLE
+ || m_state->GetState () == PhySimWifiPhy::SYNCING
+ || m_state->GetState () == PhySimWifiPhy::TX )
+ {
+ CheckForNextCcaBusyStart ();
+ }
+}
+
+std::ostream& operator<< (std::ostream& os, enum PhySimWifiPhy::State state)
+{
+ switch (state)
+ {
+ case PhySimWifiPhy::IDLE:
+ return (os << "IDLE");
+ case PhySimWifiPhy::CCA_BUSY:
+ return (os << "CCA_BUSY");
+ case PhySimWifiPhy::TX:
+ return (os << "TX");
+ case PhySimWifiPhy::SYNCING:
+ return (os << "SYNCING");
+ case PhySimWifiPhy::RX:
+ return (os << "RX");
+ default:
+ NS_FATAL_ERROR ("Invalid PhySimWifiPhy state");
+ return (os << "INVALID");
+ }
+}
+
+} // namespace ns3
« no previous file with comments | « src/contrib/physim-wifi/model/physim-wifi-phy.h ('k') | src/contrib/physim-wifi/model/physim-wifi-phy-state-helper.h » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b