diff --git a/src/lr-wpan/model/lr-wpan-phy.cc b/src/lr-wpan/model/lr-wpan-phy.cc index 9ec5373d2..6db6cd869 100644 --- a/src/lr-wpan/model/lr-wpan-phy.cc +++ b/src/lr-wpan/model/lr-wpan-phy.cc @@ -262,7 +262,9 @@ LrWpanPhy::StartRx (Ptr spectrumRxParams) if (!m_edRequest.IsExpired ()) { // Update the average receive power during ED. - m_edPower.averagePower += LrWpanSpectrumValueHelper::TotalAvgPower (m_signal->GetSignalPsd ()) * (Simulator::Now () - m_edPower.lastUpdate).GetTimeStep () / m_edPower.measurementLength.GetTimeStep (); + Time now = Simulator::Now (); + m_edPower.averagePower += LrWpanSpectrumValueHelper::TotalAvgPower (m_signal->GetSignalPsd ()) * (now - m_edPower.lastUpdate).GetTimeStep () / m_edPower.measurementLength.GetTimeStep (); + m_edPower.lastUpdate = now; } // Prevent PHY from receiving another packet while switching the transceiver state. @@ -400,7 +402,9 @@ LrWpanPhy::EndRx (Ptr params) if (!m_edRequest.IsExpired ()) { // Update the average receive power during ED. - m_edPower.averagePower += LrWpanSpectrumValueHelper::TotalAvgPower (m_signal->GetSignalPsd ()) * (Simulator::Now () - m_edPower.lastUpdate).GetTimeStep () / m_edPower.measurementLength.GetTimeStep (); + Time now = Simulator::Now (); + m_edPower.averagePower += LrWpanSpectrumValueHelper::TotalAvgPower (m_signal->GetSignalPsd ()) * (now - m_edPower.lastUpdate).GetTimeStep () / m_edPower.measurementLength.GetTimeStep (); + m_edPower.lastUpdate = now; } CheckInterference (); @@ -564,7 +568,7 @@ void LrWpanPhy::PlmeEdRequest (void) { NS_LOG_FUNCTION (this); - if (m_trxState == IEEE_802_15_4_PHY_RX_ON) + if (m_trxState == IEEE_802_15_4_PHY_RX_ON || m_trxState == IEEE_802_15_4_PHY_BUSY_RX) { // Average over the powers of all signals received until EndEd() m_edPower.averagePower = 0; @@ -574,9 +578,15 @@ LrWpanPhy::PlmeEdRequest (void) } else { + LrWpanPhyEnumeration result = m_trxState; + if (m_trxState == IEEE_802_15_4_PHY_BUSY_TX) + { + result = IEEE_802_15_4_PHY_TX_ON; + } + if (!m_plmeEdConfirmCallback.IsNull ()) { - m_plmeEdConfirmCallback (m_trxState, 0); + m_plmeEdConfirmCallback (result, 0); } } } @@ -672,6 +682,8 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state) // a packet being actively received) if (state == IEEE_802_15_4_PHY_TRX_OFF) { + CancelEd (state); + if ((m_trxState == IEEE_802_15_4_PHY_BUSY_RX) && (m_currentRxPacket.first) && (!m_currentRxPacket.second)) { @@ -692,6 +704,8 @@ LrWpanPhy::PlmeSetTRXStateRequest (LrWpanPhyEnumeration state) if (state == IEEE_802_15_4_PHY_TX_ON) { + CancelEd (state); + NS_LOG_DEBUG ("turn on PHY_TX_ON"); if ((m_trxState == IEEE_802_15_4_PHY_BUSY_RX) || (m_trxState == IEEE_802_15_4_PHY_RX_ON)) { @@ -986,6 +1000,22 @@ LrWpanPhy::PhyIsBusy (void) const || (m_trxState == IEEE_802_15_4_PHY_BUSY)); } +void +LrWpanPhy::CancelEd (LrWpanPhyEnumeration state) +{ + NS_LOG_FUNCTION (this); + NS_ASSERT (state == IEEE_802_15_4_PHY_TRX_OFF || state == IEEE_802_15_4_PHY_TX_ON); + + if (!m_edRequest.IsExpired ()) + { + m_edRequest.Cancel (); + if (!m_plmeEdConfirmCallback.IsNull ()) + { + m_plmeEdConfirmCallback (state, 0); + } + } +} + void LrWpanPhy::EndEd () { @@ -1009,7 +1039,7 @@ LrWpanPhy::EndEd () else { // in-between with linear increase per sec 6.9.7 - energyLevel = (uint8_t)((ratio / 10.0 - 1.0) * (255.0 / 3.0)); + energyLevel = static_cast (((ratio - 10.0) / 30.0) * 255.0); } if (!m_plmeEdConfirmCallback.IsNull ()) diff --git a/src/lr-wpan/model/lr-wpan-phy.h b/src/lr-wpan/model/lr-wpan-phy.h index f40055684..f653fc801 100644 --- a/src/lr-wpan/model/lr-wpan-phy.h +++ b/src/lr-wpan/model/lr-wpan-phy.h @@ -396,6 +396,8 @@ private: void CheckInterference (); void EndRx (Ptr params); + void CancelEd (LrWpanPhyEnumeration state); + void EndEd (); void EndCca (); void EndSetTRXState (); diff --git a/src/lr-wpan/test/lr-wpan-ed-test.cc b/src/lr-wpan/test/lr-wpan-ed-test.cc new file mode 100644 index 000000000..495607a43 --- /dev/null +++ b/src/lr-wpan/test/lr-wpan-ed-test.cc @@ -0,0 +1,249 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 Fraunhofer FKIE + * + * 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: + * Sascha Alexander Jopen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("lr-wpan-ed-test"); + +using namespace ns3; + +class LrWpanEdTestCase : public TestCase +{ +public: + LrWpanEdTestCase (); + +private: + virtual void DoRun (void); + + void PlmeEdConfirm (LrWpanPhyEnumeration status, uint8_t level); + + LrWpanPhyEnumeration m_status; + uint8_t m_level; +}; + +LrWpanEdTestCase::LrWpanEdTestCase () + : TestCase ("Test the 802.15.4 energie detection") +{ + m_status = IEEE_802_15_4_PHY_UNSPECIFIED; + m_level = 0; +} + +void +LrWpanEdTestCase::PlmeEdConfirm (LrWpanPhyEnumeration status, uint8_t level) +{ + NS_LOG_UNCOND ("ED completed with status " << LrWpanHelper::LrWpanPhyEnumerationPrinter(status) << " and energy level " << static_cast (level)); + m_status = status; + m_level = level; +} + +void +LrWpanEdTestCase::DoRun (void) +{ + // Tx Power: 0 dBm + // Receiver Sensitivity: -106.58 dBm + // Do energy detection for a single packet, arriving with 5 dB, 10 dB, 25 dB, + // 40 dB, relative to RX Power / Sensitivity. This should yield 0, 0, 127, + // and 255 as the reported energy levels. + // TODO: Maybe there should be a test for several interfering packets. + // TODO: There should be tests for signals not originating from 802.15.4 + // devices. + + // Test setup: + // Two nodes in communication range. The propagation model is adjusted to + // give us the above mentioned RX powers. + // Node 1 sends a packet to node 2. Node 2 starts energy detection, while the + // packet reception is in progress. The detected energy level is compared to + // the expected values. + + // Enable calculation of FCS in the trailers. Only necessary when interacting with real devices or wireshark. + // GlobalValue::Bind ("ChecksumEnabled", BooleanValue (true)); + + // Create 2 nodes, and a NetDevice for each one + Ptr n0 = CreateObject (); + Ptr n1 = CreateObject (); + + Ptr dev0 = CreateObject (); + Ptr dev1 = CreateObject (); + + dev0->SetAddress (Mac16Address ("00:01")); + dev1->SetAddress (Mac16Address ("00:02")); + + // Each device must be attached to the same channel + Ptr channel = CreateObject (); + Ptr propModel = CreateObject (); + Ptr delayModel = CreateObject (); + channel->AddPropagationLossModel (propModel); + channel->SetPropagationDelayModel (delayModel); + + dev0->SetChannel (channel); + dev1->SetChannel (channel); + + // To complete configuration, a LrWpanNetDevice must be added to a node + n0->AddDevice (dev0); + n1->AddDevice (dev1); + + Ptr sender0Mobility = CreateObject (); + sender0Mobility->SetPosition (Vector (0, 0, 0)); + dev0->GetPhy ()->SetMobility (sender0Mobility); + Ptr sender1Mobility = CreateObject (); + // Configure position 10 m distance + sender1Mobility->SetPosition (Vector (0, 10, 0)); + dev1->GetPhy ()->SetMobility (sender1Mobility); + + // Set the ED confirm callback. + dev0->GetPhy ()->SetPlmeEdConfirmCallback (MakeCallback (&LrWpanEdTestCase::PlmeEdConfirm, this)); + dev1->GetPhy ()->SetPlmeEdConfirmCallback (MakeCallback (&LrWpanEdTestCase::PlmeEdConfirm, this)); + + // Configure the RX Power to be -107.58 dBm, i.e. 1 dB below receiver sensitivity. + propModel->SetRss (-107.58); + + m_status = IEEE_802_15_4_PHY_UNSPECIFIED; + m_level = 0; + Ptr p0 = Create (100); // 100 bytes of dummy data + McpsDataRequestParams params; + params.m_srcAddrMode = SHORT_ADDR; + params.m_dstAddrMode = SHORT_ADDR; + params.m_dstPanId = 0; + params.m_dstAddr = Mac16Address ("00:02"); + params.m_msduHandle = 0; + params.m_txOptions = TX_OPTION_NONE; + Simulator::ScheduleNow (&LrWpanMac::McpsDataRequest, dev0->GetMac (), params, p0); + + Simulator::Schedule (Seconds (0.0025), &LrWpanPhy::PlmeEdRequest, dev1->GetPhy ()); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_status, IEEE_802_15_4_PHY_SUCCESS, "ED status SUCCESS (as expected)"); + NS_TEST_EXPECT_MSG_EQ (m_level, 0, "ED reported signal level 0 (as expected)"); + + + // Configure the RX Power to be -106.58 dBm, i.e. exectly to receiver sensitivity. + propModel->SetRss (-106.58); + + m_status = IEEE_802_15_4_PHY_UNSPECIFIED; + m_level = 0; + Ptr p1 = Create (100); // 100 bytes of dummy data + params.m_srcAddrMode = SHORT_ADDR; + params.m_dstAddrMode = SHORT_ADDR; + params.m_dstPanId = 0; + params.m_dstAddr = Mac16Address ("00:02"); + params.m_msduHandle = 0; + params.m_txOptions = TX_OPTION_NONE; + Simulator::ScheduleNow (&LrWpanMac::McpsDataRequest, dev0->GetMac (), params, p1); + + Simulator::Schedule (Seconds (0.0025), &LrWpanPhy::PlmeEdRequest, dev1->GetPhy ()); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_status, IEEE_802_15_4_PHY_SUCCESS, "ED status SUCCESS (as expected)"); + NS_TEST_EXPECT_MSG_EQ (m_level, 0, "ED reported signal level 0 (as expected)"); + + + // Configure the RX Power to be -81.58 dBm, i.e. 25 dB above receiver sensitivity. + propModel->SetRss (-81.58); + + m_status = IEEE_802_15_4_PHY_UNSPECIFIED; + m_level = 0; + Ptr p2 = Create (100); // 100 bytes of dummy data + params.m_srcAddrMode = SHORT_ADDR; + params.m_dstAddrMode = SHORT_ADDR; + params.m_dstPanId = 0; + params.m_dstAddr = Mac16Address ("00:02"); + params.m_msduHandle = 0; + params.m_txOptions = TX_OPTION_NONE; + Simulator::ScheduleNow (&LrWpanMac::McpsDataRequest, dev0->GetMac (), params, p2); + + Simulator::Schedule (Seconds (0.0025), &LrWpanPhy::PlmeEdRequest, dev1->GetPhy ()); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_status, IEEE_802_15_4_PHY_SUCCESS, "ED status SUCCESS (as expected)"); + NS_TEST_EXPECT_MSG_EQ (m_level, 127, "ED reported signal level 127 (as expected)"); + + + // Configure the RX Power to be -66.58 dBm, i.e. 40 dB above receiver sensitivity. + propModel->SetRss (-66.58); + + m_status = IEEE_802_15_4_PHY_UNSPECIFIED; + m_level = 0; + Ptr p3 = Create (100); // 100 bytes of dummy data + params.m_srcAddrMode = SHORT_ADDR; + params.m_dstAddrMode = SHORT_ADDR; + params.m_dstPanId = 0; + params.m_dstAddr = Mac16Address ("00:02"); + params.m_msduHandle = 0; + params.m_txOptions = TX_OPTION_NONE; + Simulator::ScheduleNow (&LrWpanMac::McpsDataRequest, dev0->GetMac (), params, p3); + + Simulator::Schedule (Seconds (0.0025), &LrWpanPhy::PlmeEdRequest, dev1->GetPhy ()); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_status, IEEE_802_15_4_PHY_SUCCESS, "ED status SUCCESS (as expected)"); + NS_TEST_EXPECT_MSG_EQ (m_level, 255, "ED reported signal level 255 (as expected)"); + + // Test ED at sender. + m_status = IEEE_802_15_4_PHY_UNSPECIFIED; + m_level = 0; + Ptr p4 = Create (100); // 100 bytes of dummy data + params.m_srcAddrMode = SHORT_ADDR; + params.m_dstAddrMode = SHORT_ADDR; + params.m_dstPanId = 0; + params.m_dstAddr = Mac16Address ("00:02"); + params.m_msduHandle = 0; + params.m_txOptions = TX_OPTION_NONE; + Simulator::ScheduleNow (&LrWpanMac::McpsDataRequest, dev0->GetMac (), params, p4); + + Simulator::Schedule (Seconds (0.0025), &LrWpanPhy::PlmeEdRequest, dev0->GetPhy ()); + + Simulator::Run (); + + NS_TEST_EXPECT_MSG_EQ (m_status, IEEE_802_15_4_PHY_TX_ON, "ED status TX_ON (as expected)"); + NS_TEST_EXPECT_MSG_EQ (m_level, 0, "ED reported signal level 0 (as expected)"); + + Simulator::Destroy (); +} + +class LrWpanEdTestSuite : public TestSuite +{ +public: + LrWpanEdTestSuite (); +}; + +LrWpanEdTestSuite::LrWpanEdTestSuite () + : TestSuite ("lr-wpan-ed", UNIT) +{ + AddTestCase (new LrWpanEdTestCase, TestCase::QUICK); +} + +static LrWpanEdTestSuite g_lrWpanEdTestSuite; diff --git a/src/lr-wpan/wscript b/src/lr-wpan/wscript index 7c5a9539f..acf0437df 100644 --- a/src/lr-wpan/wscript +++ b/src/lr-wpan/wscript @@ -21,6 +21,7 @@ def build(bld): module_test.source = [ 'test/lr-wpan-ack-test.cc', 'test/lr-wpan-collision-test.cc', + 'test/lr-wpan-ed-test.cc', 'test/lr-wpan-error-model-test.cc', 'test/lr-wpan-packet-test.cc', 'test/lr-wpan-pd-plme-sap-test.cc',