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

Unified Diff: src/lorawan/model/gateway-lora-phy.cc

Issue 331760043: LoRaWAN module review request
Patch Set: Created 6 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
« no previous file with comments | « src/lorawan/model/gateway-lora-phy.h ('k') | src/lorawan/model/gateway-status.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/lorawan/model/gateway-lora-phy.cc
===================================================================
new file mode 100644
--- /dev/null
+++ b/src/lorawan/model/gateway-lora-phy.cc
@@ -0,0 +1,408 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2017 University of Padova
+ *
+ * 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: Davide Magrin <magrinda@dei.unipd.it>
+ */
+
+#include "ns3/gateway-lora-phy.h"
+#include "ns3/lora-tag.h"
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("GatewayLoraPhy");
+
+NS_OBJECT_ENSURE_REGISTERED (GatewayLoraPhy);
+
+/**************************************
+ * ReceptionPath implementation *
+ **************************************/
+GatewayLoraPhy::ReceptionPath::ReceptionPath(double frequencyMHz) :
+ m_frequencyMHz (frequencyMHz),
+ m_available (1),
+ m_event (0)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+GatewayLoraPhy::ReceptionPath::~ReceptionPath(void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+double
+GatewayLoraPhy::ReceptionPath::GetFrequency (void)
+{
+ return m_frequencyMHz;
+}
+
+bool
+GatewayLoraPhy::ReceptionPath::IsAvailable (void)
+{
+ return m_available;
+}
+
+void
+GatewayLoraPhy::ReceptionPath::Free (void)
+{
+ m_available = true;
+ m_event = 0;
+}
+
+void
+GatewayLoraPhy::ReceptionPath::LockOnEvent (Ptr<LoraInterferenceHelper::Event>
+ event)
+{
+ m_available = false;
+ m_event = event;
+}
+
+void
+GatewayLoraPhy::ReceptionPath::SetEvent (Ptr<LoraInterferenceHelper::Event>
+ event)
+{
+ m_event = event;
+}
+
+Ptr<LoraInterferenceHelper::Event>
+GatewayLoraPhy::ReceptionPath::GetEvent (void)
+{
+ return m_event;
+}
+
+void
+GatewayLoraPhy::ReceptionPath::SetFrequency (double frequencyMHz)
+{
+ m_frequencyMHz = frequencyMHz;
+}
+
+/***********************************************************************
+ * Implementation of Gateway methods *
+ ***********************************************************************/
+
+TypeId
+GatewayLoraPhy::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::GatewayLoraPhy")
+ .SetParent<LoraPhy> ()
+ .SetGroupName ("lorawan")
+ .AddConstructor<GatewayLoraPhy> ()
+ .AddTraceSource ("LostPacketBecauseNoMoreReceivers",
+ "Trace source indicating a packet "
+ "could not be correctly received because"
+ "there are no more demodulators available",
+ MakeTraceSourceAccessor
+ (&GatewayLoraPhy::m_noMoreDemodulators),
+ "ns3::Packet::TracedCallback")
+ .AddTraceSource ("OccupiedReceptionPaths",
+ "Number of currently occupied reception paths",
+ MakeTraceSourceAccessor
+ (&GatewayLoraPhy::m_occupiedReceptionPaths),
+ "ns3::TracedValueCallback::Int");
+ return tid;
+}
+
+GatewayLoraPhy::GatewayLoraPhy () :
+ m_isTransmitting (false)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+GatewayLoraPhy::~GatewayLoraPhy ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+// Uplink sensitivity (Source: SX1301 datasheet)
+// {SF7, SF8, SF9, SF10, SF11, SF12}
+const double GatewayLoraPhy::sensitivity[6] =
+{-130.0, -132.5, -135.0, -137.5, -140.0, -142.5};
+
+void
+GatewayLoraPhy::AddReceptionPath (double frequencyMHz)
+{
+ NS_LOG_FUNCTION (this << frequencyMHz);
+
+ m_receptionPaths.push_back (Create<GatewayLoraPhy::ReceptionPath>
+ (frequencyMHz));
+}
+
+void
+GatewayLoraPhy::ResetReceptionPaths (void)
+{
+ NS_LOG_FUNCTION (this);
+
+ m_receptionPaths.clear ();
+}
+
+void
+GatewayLoraPhy::Send (Ptr<Packet> packet, LoraTxParameters txParams,
+ double frequencyMHz, double txPowerDbm)
+{
+ NS_LOG_FUNCTION (this << packet << frequencyMHz << txPowerDbm);
+
+ // Get the time a packet with these parameters will take to be transmitted
+ Time duration = GetOnAirTime (packet, txParams);
+
+ /*
+ * Differently from what is done in EndDevices, where packets cannot be
+ * transmitted while in RX state, Gateway sending is assumed to have priority
+ * over reception.
+ *
+ * This different behaviour is motivated by the asymmetry in a typical
+ * LoRaWAN network, where Downlink messages are more critical to network
+ * performance than Uplink ones. Even if the gateway is receiving a packet
+ * on the channel when it is asked to transmit by the upper layer, in order
+ * not to miss the receive window of the end device, the gateway will still
+ * need to send the packet. In order to model this fact, the send event is
+ * registered in the gateway's InterferenceHelper as a received event.
+ * While this may not destroy packets incoming on the same frequency, this
+ * is almost always guaranteed to do so due to the fact that this event can
+ * have a power up to 27 dBm.
+ */
+ m_interference.Add (duration, txPowerDbm, txParams.sf, packet, frequencyMHz);
+
+ // Send the packet in the channel
+ m_channel->Send (this, packet, txPowerDbm, txParams, duration, frequencyMHz);
+
+ Simulator::Schedule (duration, &GatewayLoraPhy::TxFinished, this, packet);
+
+ m_isTransmitting = true;
+
+ // Fire the trace source
+ if (m_device)
+ {
+ m_startSending (packet, m_device->GetNode ()->GetId ());
+ }
+ else
+ {
+ m_startSending (packet, 0);
+ }
+}
+
+void
+GatewayLoraPhy::TxFinished (Ptr<Packet> packet)
+{
+ m_isTransmitting = false;
+}
+
+bool
+GatewayLoraPhy::IsTransmitting (void)
+{
+ return m_isTransmitting;
+}
+
+void
+GatewayLoraPhy::StartReceive (Ptr<Packet> packet, double rxPowerDbm,
+ uint8_t sf, Time duration, double frequencyMHz)
+{
+ NS_LOG_FUNCTION (this << packet << rxPowerDbm << duration << frequencyMHz);
+
+ // Fire the trace source
+ m_phyRxBeginTrace (packet);
+
+ // Add the event to the LoraInterferenceHelper
+ Ptr<LoraInterferenceHelper::Event> event;
+ event = m_interference.Add (duration, rxPowerDbm, sf, packet, frequencyMHz);
+
+ // Cycle over the receive paths to check availability to receive the packet
+ std::list<Ptr<GatewayLoraPhy::ReceptionPath> >::iterator it;
+
+ for (it = m_receptionPaths.begin (); it != m_receptionPaths.end (); ++it)
+ {
+ Ptr<GatewayLoraPhy::ReceptionPath> currentPath = *it;
+
+ NS_LOG_DEBUG ("Current ReceptionPath is centered on frequency = " <<
+ currentPath->GetFrequency ());
+
+ // If the receive path is available and listening on the channel of
+ // interest, we have a candidate
+ if (currentPath->GetFrequency () == frequencyMHz &&
+ currentPath->IsAvailable ())
+ {
+ // See whether the reception power is above or below the sensitivity
+ // for that spreading factor
+ double sensitivity = GatewayLoraPhy::sensitivity[unsigned(sf)-7];
+
+ if (rxPowerDbm < sensitivity) // Packet arrived below sensitivity
+ {
+ NS_LOG_INFO ("Dropping packet reception of packet with sf = "
+ << unsigned(sf) <<
+ " because under the sensitivity of "
+ << sensitivity << " dBm");
+
+ if (m_device)
+ {
+ m_underSensitivity (packet, m_device->GetNode ()->GetId ());
+ }
+ else
+ {
+ m_underSensitivity (packet, 0);
+ }
+
+ // Since the packet is below sensitivity, it makes no sense to
+ // search for another ReceivePath
+ return;
+ }
+ else // We have sufficient sensitivity to start receiving
+ {
+ NS_LOG_INFO ("Scheduling reception of a packet, " <<
+ "occupying one demodulator");
+
+ // Block this resource
+ currentPath->LockOnEvent (event);
+ m_occupiedReceptionPaths++;
+
+ // Schedule the end of the reception of the packet
+ Simulator::Schedule (duration, &LoraPhy::EndReceive, this,
+ packet, event);
+
+ // Make sure we don't go on searching for other ReceivePaths
+ return;
+ }
+ }
+ }
+ // If we get to this point, there are no demodulators we can use
+ NS_LOG_INFO ("Dropping packet reception of packet with sf = "
+ << unsigned(sf) <<
+ " because no suitable demodulator was found");
+
+ // Fire the trace source
+ if (m_device)
+ {
+ m_noMoreDemodulators (packet, m_device->GetNode ()->GetId ());
+ }
+ else
+ {
+ m_noMoreDemodulators (packet, 0);
+ }
+}
+
+void
+GatewayLoraPhy::EndReceive (Ptr<Packet> packet,
+ Ptr<LoraInterferenceHelper::Event> event)
+{
+ NS_LOG_FUNCTION (this << packet << *event);
+
+ // Call the trace source
+ m_phyRxEndTrace (packet);
+
+ // Call the LoraInterferenceHelper to determine whether there was
+ // destructive interference. If the packet is correctly received, this
+ // method returns a 0.
+ uint8_t packetDestroyed = 0;
+ packetDestroyed = m_interference.IsDestroyedByInterference (event);
+
+ // Check whether the packet was destroyed
+ if (packetDestroyed != uint8_t (0))
+ {
+ NS_LOG_DEBUG ("packetDestroyed by " << unsigned(packetDestroyed));
+
+ // Update the packet's LoraTag
+ LoraTag tag;
+ packet->RemovePacketTag (tag);
+ tag.SetDestroyedBy (packetDestroyed);
+ packet->AddPacketTag (tag);
+
+ // Fire the trace source
+ if (m_device)
+ {
+ m_interferedPacket (packet, m_device->GetNode ()->GetId ());
+ }
+ else
+ {
+ m_interferedPacket (packet, 0);
+ }
+ }
+ else // Reception was correct
+ {
+ NS_LOG_INFO ("Packet with SF " <<
+ unsigned(event->GetSpreadingFactor ()) <<
+ " received correctly");
+
+ // Fire the trace source
+ if (m_device)
+ {
+ m_successfullyReceivedPacket (packet, m_device->GetNode ()->GetId ());
+ }
+ else
+ {
+ m_successfullyReceivedPacket (packet, 0);
+ }
+
+ // Forward the packet to the upper layer
+ if (!m_rxOkCallback.IsNull ())
+ {
+ // Make a copy of the packet
+ Ptr<Packet> packetCopy = packet->Copy ();
+
+ // Set the receive power and frequency of this packet in the LoraTag: this
+ // information can be useful for upper layers trying to control link
+ // quality.
+ LoraTag tag;
+ packetCopy->RemovePacketTag (tag);
+ tag.SetReceivePower (event->GetRxPowerdBm ());
+ tag.SetFrequency (event->GetFrequency ());
+ packetCopy->AddPacketTag (tag);
+
+ m_rxOkCallback (packetCopy);
+ }
+
+ }
+
+ // Search for the demodulator that was locked on this event to free it.
+
+ std::list< Ptr< GatewayLoraPhy::ReceptionPath > >::iterator it;
+
+ for (it = m_receptionPaths.begin (); it != m_receptionPaths.end (); ++it)
+ {
+ Ptr<GatewayLoraPhy::ReceptionPath> currentPath = *it;
+
+ if (currentPath->GetEvent () == event)
+ {
+ currentPath->Free ();
+ m_occupiedReceptionPaths--;
+ return;
+ }
+ }
+}
+
+bool
+GatewayLoraPhy::IsOnFrequency (double frequencyMHz)
+{
+ NS_LOG_FUNCTION (this << frequencyMHz);
+
+ // Search every demodulator to see whether there's one listening on this
+ // frequency.
+ std::list< Ptr< GatewayLoraPhy::ReceptionPath > >::iterator it;
+
+ for (it = m_receptionPaths.begin (); it != m_receptionPaths.end (); ++it)
+ {
+ Ptr<GatewayLoraPhy::ReceptionPath> currentPath = *it;
+
+ NS_LOG_DEBUG ("Current reception path is on frequency " <<
+ currentPath->GetFrequency ());
+
+ if (currentPath->GetFrequency () == frequencyMHz)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+}
« no previous file with comments | « src/lorawan/model/gateway-lora-phy.h ('k') | src/lorawan/model/gateway-status.h » ('j') | no next file with comments »

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