A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
simple-end-device-lora-phy.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2017 University of Padova
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Davide Magrin <magrinda@dei.unipd.it>
7 */
8
10
11#include "lora-channel.h"
12#include "lora-tag.h"
13
14#include "ns3/node.h"
15#include "ns3/simulator.h"
16
17namespace ns3
18{
19namespace lorawan
20{
21
22NS_LOG_COMPONENT_DEFINE("SimpleEndDeviceLoraPhy");
23
25
26TypeId
28{
29 static TypeId tid = TypeId("ns3::SimpleEndDeviceLoraPhy")
31 .SetGroupName("lorawan")
32 .AddConstructor<SimpleEndDeviceLoraPhy>();
33
34 return tid;
35}
36
41
46
47void
49 uint32_t frequencyHz,
50 IQPolarity iqPolarity,
51 const LoraTxParameters& txParams,
52 double txPowerDbm)
53{
54 NS_LOG_FUNCTION(this << packet << frequencyHz << iqPolarity << txParams << txPowerDbm);
55
56 // We must be either in SLEEP or STANDBY mode to send a packet
57 if (auto state = GetState(); state != State::SLEEP && state != State::STANDBY)
58 {
59 NS_LOG_ERROR("Cannot send because device is currently not in SLEEP or STANDBY mode");
60 return;
61 }
62
63 // Write hardware registers of the LoRa chip
64 m_regs.spreadingFactor = txParams.spreadingFactor;
65 m_regs.bandwidthHz = txParams.bandwidthHz;
66 m_regs.codingRate = txParams.codingRate;
67 m_regs.lowDataRateOptimize = txParams.lowDataRateOptimize;
68 m_regs.preambleLenSymb = txParams.preambleLenSymb;
69 m_regs.implicitHeader = txParams.implicitHeader;
70 m_regs.payloadLenBytes = packet->GetSize();
71 m_regs.crcEnabled = txParams.crcEnabled;
72 m_regs.iqPolarity = iqPolarity;
73 m_regs.frequencyHz = frequencyHz;
74 m_regs.txPowerDbm = txPowerDbm;
75
76 // Tag the packet with information about its Spreading Factor
77 LoraTag tag;
78 packet->RemovePacketTag(tag);
79 tag.SetSpreadingFactor(m_regs.spreadingFactor);
80 packet->AddPacketTag(tag);
81
82 // Switch to the TX state
84 // Call the trace source
85 m_startSending(packet, (m_device) ? m_device->GetNode()->GetId() : 0);
86
87 // Compute the duration of the modulated transmission
88 Time duration = GetTimeOnAir(packet->GetSize(), txParams);
89 // Propagate the transmission over the channel (schedule StartReceive for other nodes)
90 m_channel->Send(this, packet, frequencyHz, iqPolarity, txParams, txPowerDbm, duration);
91
92 // Schedule a call to self to signal the transmission modulation end
94}
95
96void
98 uint32_t frequencyHz,
99 IQPolarity iqPolarity,
100 uint8_t spreadingFactor,
101 double rxPowerDbm,
102 Time duration)
103{
104 NS_LOG_FUNCTION(this << packet << frequencyHz << iqPolarity << unsigned(spreadingFactor)
105 << rxPowerDbm << duration);
106
107 // Notify the LoraInterferenceHelper of the impinging signal, and remember
108 // the event it creates. This will be used then to correctly handle the end
109 // of reception event.
110 //
111 // We need to do this regardless of our state or frequency, since these could
112 // change (and making the interference relevant) while the interference is
113 // still incoming.
114 auto event = m_interference.Add(duration, rxPowerDbm, spreadingFactor, packet, frequencyHz);
115
116 // Check that the current PHY state is RX_ENABLED
117 if (auto state = GetState(); state != State::RX_ENABLED)
118 {
119 if (state == State::RX_ACTIVE)
120 {
121 NS_LOG_INFO("Device already locked onto another transmission");
122 }
123 else
124 {
125 NS_LOG_INFO("Dropping packet because device is in " << state << " state");
126 }
127 return;
128 }
129
130 // If we are in RX_ENABLED mode, we can potentially lock on the currently incoming
131 // transmission There are a series of properties the packet needs to respect in order
132 // for us to be able to lock on it:
133 // - It's on frequency we are listening on
134 // - It's using the right modulation polarity (uplink or downlink)
135 // - It uses the spreading factor we are configured to look for
136 // - Its receive power is above the device sensitivity for that spreading factor
137
138 // Check frequency
139 if (frequencyHz != m_regs.frequencyHz)
140 {
141 NS_LOG_INFO("Packet ignored because it's on frequency "
142 << frequencyHz << " Hz and we are listening to " << m_regs.frequencyHz
143 << " Hz");
144 // Fire the trace source for this event.
145 m_wrongFrequency(packet, (m_device) ? m_device->GetNode()->GetId() : 0);
146 return;
147 }
148 // Check modulation I/Q polarity
149 else if (iqPolarity != m_regs.iqPolarity)
150 {
151 NS_LOG_INFO("Packet ignored because it's " << iqPolarity << "LINK and we are listening for "
152 << m_regs.iqPolarity << "LINK transmissions");
153 // Fire the trace source for this event.
154 m_wrongPolarity(packet, (m_device) ? m_device->GetNode()->GetId() : 0);
155 return;
156 }
157 // Check Spreading Factor
158 else if (spreadingFactor != m_regs.spreadingFactor)
159 {
160 NS_LOG_INFO("Packet lost because it's using SF" << unsigned(spreadingFactor)
161 << ", while we are listening for SF"
162 << unsigned(m_regs.spreadingFactor));
163 // Fire the trace source for this event.
164 m_wrongSf(packet, (m_device) ? m_device->GetNode()->GetId() : 0);
165 return;
166 }
167 // Check Sensitivity
168 else if (double sens = EndDeviceLoraPhy::SENSITIVITY[spreadingFactor - 7]; rxPowerDbm < sens)
169 {
170 NS_LOG_INFO("Dropping packet reception of packet with SF"
171 << unsigned(spreadingFactor) << " because under the sensitivity of " << sens
172 << " dBm");
173 // Fire the trace source for this event.
174 m_underSensitivity(packet, (m_device) ? m_device->GetNode()->GetId() : 0);
175 return;
176 }
177
178 // Preamble detected, we lock onto the transmission and start receiving
180 // Fire the beginning of reception trace source
181 m_phyRxBeginTrace(packet);
182
183 // Schedule the end of the reception of the packet
184 NS_LOG_INFO("Scheduling reception of a packet. End in " << duration.As(Time::S));
185 Simulator::Schedule(duration, &SimpleEndDeviceLoraPhy::EndReceive, this, packet, event);
186}
187
188void
190{
191 NS_LOG_FUNCTION(this << packet << event);
192
193 // The demodulation terminated, automatically switch to Standby
194 DoEndReceive();
195 // Fire the trace source
196 m_phyRxEndTrace(packet);
197
198 // Call the LoraInterferenceHelper to determine whether there was destructive
199 // interference on this event.
200 if (m_interference.IsDestroyedByInterference(event))
201 {
202 NS_LOG_INFO("Packet destroyed by interference");
203 // Fire the trace source if packet was destroyed
204 m_interferedPacket(packet, (m_device) ? m_device->GetNode()->GetId() : 0);
205 // If there is one, perform the callback to inform the upper layer of the
206 // lost packet
207 if (!m_rxFailedCallback.IsNull())
208 {
209 m_rxFailedCallback(packet);
210 }
211 return;
212 }
213
214 NS_LOG_INFO("Packet received correctly");
215 m_successfullyReceivedPacket(packet, (m_device) ? m_device->GetNode()->GetId() : 0);
216
217 LoraTag tag;
218 packet->RemovePacketTag(tag);
219 tag.SetReceivePower(event->GetRxPowerDbm());
220 tag.SetFrequency(event->GetFrequency());
221 packet->AddPacketTag(tag);
222
223 // If there is one, perform the callback to inform the upper layer
224 if (!m_rxOkCallback.IsNull())
225 {
226 m_rxOkCallback(packet);
227 }
228}
229
230} // namespace lorawan
231} // namespace ns3
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:408
@ S
second
Definition nstime.h:106
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
State GetState()
Return the internal state this end device is currently in.
TracedCallback< Ptr< const Packet >, uint32_t > m_wrongPolarity
Trace source for when a packet is lost because it was transmitted with a different I/Q polarity (upli...
static const double SENSITIVITY[6]
The sensitivity vector of this device to different SFs.
EndDeviceLoraRegisters m_regs
High level model of LoRa chip registers.
void DoStartReceive()
This function should be called by parent classes to signal that the PHY is starting to demodulate a t...
EndDeviceLoraPhy()
Default constructor.
void DoEndReceive()
This function should be called by parent classes to signal that the PHY is finishing to demodulate a ...
TracedCallback< Ptr< const Packet >, uint32_t > m_wrongSf
Trace source for when a packet is lost because it was using a spreading factor different from the one...
void RequestTxMode()
This function puts the PHY in transmission mode.
@ RX_ACTIVE
The PHY layer is actively receiving a transmission after locking onto a preamble.
@ SLEEP
The PHY layer is in low-power sleep state.
@ RX_ENABLED
The PHY layer is listening to the channel for a valid transmission preamble.
@ STANDBY
The PHY layer is in standby mode.
void TxFinished(Ptr< const Packet > packet) override
Internal call when transmission of a packet finishes.
TracedCallback< Ptr< const Packet >, uint32_t > m_wrongFrequency
Trace source for when a packet is lost because it was transmitted on a frequency different from the o...
TracedCallback< Ptr< const Packet > > m_phyRxEndTrace
The trace source fired when a packet reception ends.
Definition lora-phy.h:328
LoraInterferenceHelper m_interference
The LoraInterferenceHelper associated to this PHY.
Definition lora-phy.h:310
TracedCallback< Ptr< const Packet >, uint32_t > m_interferedPacket
The trace source fired when a packet cannot be correctly received because of interference.
Definition lora-phy.h:345
RxFailedCallback m_rxFailedCallback
The callback to perform upon failed reception of a packet we were locked on.
Definition lora-phy.h:302
static Time GetTimeOnAir(uint32_t phyPayloadLen, const LoraTxParameters &txParams)
Compute the total transmission time for a physical packet based on modulation parameters.
Definition lora-phy.cc:110
TracedCallback< Ptr< const Packet >, uint32_t > m_successfullyReceivedPacket
The trace source fired when a packet was correctly received.
Definition lora-phy.h:333
TracedCallback< Ptr< const Packet >, uint32_t > m_startSending
The trace source fired when a packet is sent.
Definition lora-phy.h:317
TracedCallback< Ptr< const Packet >, uint32_t > m_underSensitivity
The trace source fired when a packet cannot be received because its power is below the sensitivity th...
Definition lora-phy.h:339
Ptr< NetDevice > m_device
The net device this PHY is attached to.
Definition lora-phy.h:306
TracedCallback< Ptr< const Packet > > m_phyRxBeginTrace
The trace source fired when a packet begins the reception process from the medium.
Definition lora-phy.h:323
Ptr< LoraChannel > m_channel
The channel this PHY transmits on.
Definition lora-phy.h:308
RxOkCallback m_rxOkCallback
The callback to perform upon correct reception of a packet.
Definition lora-phy.h:297
Tag used to save various data about a packet, like its Spreading Factor and data about interference.
Definition lora-tag.h:26
void SetFrequency(uint32_t frequencyHz)
Set the frequency of the packet.
Definition lora-tag.cc:116
void SetSpreadingFactor(uint8_t sf)
Set which Spreading Factor this packet was transmitted with.
Definition lora-tag.cc:104
void SetReceivePower(double receivePower)
Set the power this packet was received with.
Definition lora-tag.cc:110
Class representing a simple LoRa transceiver, with an error model based on receiver sensitivity and a...
void StartReceive(Ptr< Packet > packet, uint32_t frequencyHz, IQPolarity iqPolarity, uint8_t spreadingFactor, double rxPowerDbm, Time duration) override
Start receiving a packet.
static TypeId GetTypeId()
Register this type.
void Send(Ptr< Packet > packet, uint32_t frequencyHz, IQPolarity iqPolarity, const LoraTxParameters &txParams, double txPowerDbm) override
Instruct the PHY to send a packet according to some parameters.
void EndReceive(Ptr< Packet > packet, Ptr< LoraInterferenceHelper::Event > event) override
Finish reception of a packet.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:246
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
IQPolarity
I/Q Polarity of LoRa transmission symbols.
Definition lora-phy.h:33
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...
Definition lora-phy.h:73
CodingRate codingRate
Transmission coding rate.
Definition lora-phy.h:77
uint32_t bandwidthHz
Transmission bandwidth in Hz.
Definition lora-phy.h:76
bool implicitHeader
Whether to use implicit header mode.
Definition lora-phy.h:81
uint8_t spreadingFactor
Symbol Spreading Factor (SF).
Definition lora-phy.h:75
bool crcEnabled
Whether Cyclic Redundancy Check (CRC) is enabled.
Definition lora-phy.h:82
bool lowDataRateOptimize
Low Data Rate Optimization (mandated for SF11 and SF12).
Definition lora-phy.h:78
uint16_t preambleLenSymb
Number of symbols in the packet preamble.
Definition lora-phy.h:80