A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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 "ns3/simulator.h"
12
13namespace ns3
14{
15namespace lorawan
16{
17
18NS_LOG_COMPONENT_DEFINE("EndDeviceLoraPhy");
19
21
22TypeId
24{
25 static TypeId tid =
26 TypeId("ns3::EndDeviceLoraPhy")
28 .SetGroupName("lorawan")
29 .AddTraceSource("LostPacketBecauseWrongFrequency",
30 "Trace source indicating a packet "
31 "could not be correctly decoded because"
32 "the end device was listening on a different frequency",
34 "ns3::Packet::TracedCallback")
35 .AddTraceSource("LostPacketBecauseWrongPolarity",
36 "Trace source indicating a packet "
37 "could not be correctly decoded because"
38 "the end device was expecting a different I/Q polarity",
40 "ns3::Packet::TracedCallback")
41 .AddTraceSource("LostPacketBecauseWrongSpreadingFactor",
42 "Trace source indicating a packet "
43 "could not be correctly decoded because"
44 "the end device was listening for a different Spreading Factor",
46 "ns3::Packet::TracedCallback")
47 .AddTraceSource("EndDeviceState",
48 "The current state of the device",
50 "ns3::TracedValueCallback::EndDeviceLoraPhy::State");
51 return tid;
52}
53
54// Defaults from SX1272/73 datasheet (Rev. 4, Jan. 2019)
56 : m_regs{
57 .spreadingFactor = 7,
58 .bandwidthHz = 125000,
59 .codingRate = CodingRate::CR_4_5,
60 .lowDataRateOptimize = false,
61 .preambleLenSymb = 8,
62 .payloadLenBytes = 1,
63 .implicitHeader = false,
64 .crcEnabled = false,
65 .iqPolarity = IQPolarity::UP,
66 .frequencyHz = 915'000'000,
67 .txPowerDbm = 14,
68 .syncWord = 0xF5,
69 .symbNumTimeout = 100,
70 },
71 m_state(State::STANDBY)
72{
73 NS_LOG_FUNCTION(this);
74}
75
80
81// Sensitivity (from SX1272 datasheet)
82// {SF7, SF8, SF9, SF10, SF11, SF12}
83// These sensitivities are for a bandwidth of 125000 Hz
84const double EndDeviceLoraPhy::SENSITIVITY[6] = {-124, -127, -130, -133, -135, -137};
85
86bool
88{
89 NS_LOG_FUNCTION(this);
90 return m_state == State::TX;
91}
92
93bool
95{
96 NS_LOG_FUNCTION(this);
97 return m_regs.frequencyHz == frequencyHz;
98}
99
102{
103 NS_LOG_FUNCTION(this);
104 return m_state;
105}
106
107void
109{
110 NS_LOG_FUNCTION(this);
111 // Enter SLEEP mode
113}
114
115void
117 IQPolarity iqPolarity,
118 uint8_t spreadingFactor,
119 uint32_t bandwidthHz,
120 uint8_t symbNumTimeout,
121 RxTimeoutCallback rxTimeoutCallback)
122{
123 NS_LOG_FUNCTION(this);
124 // Write hardware registers of the LoRa chip
125 m_regs.frequencyHz = frequencyHz;
126 m_regs.bandwidthHz = bandwidthHz;
127 m_regs.iqPolarity = iqPolarity;
128 m_regs.spreadingFactor = spreadingFactor;
129 m_regs.symbNumTimeout = symbNumTimeout;
130 // Set timeout callback
131 m_rxTimeoutCallback = rxTimeoutCallback;
132 // Enter RXSINGLE mode
134}
135
136void
137EndDeviceLoraPhy::RegisterListener(const std::shared_ptr<EndDeviceLoraPhyListener>& listener)
138{
139 m_listeners.emplace_back(listener);
140}
141
142void
143EndDeviceLoraPhy::UnregisterListener(const std::shared_ptr<EndDeviceLoraPhyListener>& listener)
144{
145 m_listeners.remove_if([&listener](auto&& weakPtr) { return weakPtr.lock() == listener; });
146}
147
148// protected
149
150void
152{
153 NS_LOG_FUNCTION(this << packet);
154 NS_ASSERT_MSG(m_state == State::TX, "Improper switch to STANDBY from m_state=" << m_state);
155 // Automatically switch to STANDBY mode.
157 // Forward packet to the upper layer (if the callback was set).
158 if (!m_txFinishedCallback.IsNull())
159 {
160 m_txFinishedCallback(packet);
161 }
162}
163
164void
166{
167 NS_LOG_FUNCTION(this);
168 // Ignore if already in right state
169 if (m_state == State::SLEEP)
170 {
171 return;
172 }
173
174 if (m_state != State::STANDBY)
175 {
176 NS_LOG_ERROR("Cannot switch to SLEEP from m_state=" << m_state);
177 return;
178 }
179
181}
182
183void
189
190void
192{
193 NS_LOG_FUNCTION(this);
194 // rx single mode: switch to RX_ENABLED + start HW timer
196 auto tSym = GetTSym(m_regs.spreadingFactor, m_regs.bandwidthHz);
198 Simulator::Schedule(m_regs.symbNumTimeout * tSym, &EndDeviceLoraPhy::RxTimeout, this);
199}
200
201void
203{
204 NS_LOG_FUNCTION(this);
205 // cancel schedule RX timeout, if any
206 m_rxTimeoutEvent.Cancel();
208}
209
210void
212{
213 NS_LOG_FUNCTION(this);
215 "Improper switch to STANDBY from m_state=" << m_state);
217}
218
219// private
220
221void
223{
225 // Notify the upper layer (in reality this is an hardware interrupt)
226 if (!m_rxTimeoutCallback.IsNull())
227 {
229 }
230}
231
232void
234{
235 NS_LOG_FUNCTION(this);
236 NS_ASSERT_MSG(m_state == State::STANDBY, "Cannot switch to SLEEP from m_state=" << m_state);
238 // Notify listeners of the state change
240}
241
242void
251
252void
254{
255 NS_LOG_FUNCTION(this);
257 "Cannot switch to TX from m_state=" << m_state);
260}
261
262void
271
272void
281
282// external
283
284std::ostream&
285operator<<(std::ostream& os, const EndDeviceLoraPhy::State& state)
286{
287 switch (state)
288 {
290 return (os << "SLEEP");
292 return (os << "STANDBY");
294 return (os << "TX");
296 return (os << "RX_ENABLED");
298 return (os << "RX_ACTIVE");
299 default:
300 NS_FATAL_ERROR("Invalid LoRa device PHY state");
301 }
302}
303
304} // namespace lorawan
305} // 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
a unique identifier for an interface.
Definition type-id.h:50
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
Class representing a LoRa transceiver hardware state-machine of a SX1272 LoRa chip (see SX1272/73 Dat...
void SwitchToSleep()
Switch to the SLEEP state.
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...
void SwitchToTx()
Switch to the TX state.
bool IsOnFrequency(uint32_t frequencyHz) const override
Whether this device is listening on the specified frequency or not.
void SwitchToStandBy()
Switch to the STANDBY state.
void SwitchToRxActive()
Update the RX state to RX_ACTIVE on preamble lock.
void RequestRxSingleMode()
This function reads RX parameters from the internal registers of the PHY hardware and begins a recept...
void ReceiveSingle(uint32_t frequencyHz, IQPolarity iqPolarity, uint8_t spreadingFactor, uint32_t bandwidthHz, uint8_t symbNumTimeout, RxTimeoutCallback rxTimeoutCallback)
This function starts a reception attempt that will time-out if no transmission preamble is detected.
EventId m_rxTimeoutEvent
Event for timed switch from RX_ENABLED to STANDBY.
void SwitchToRxEnabled()
Switch to the RX_ENABLED state.
static const double SENSITIVITY[6]
The sensitivity vector of this device to different SFs.
void NotifyListeners(FUNC f, Ts &&... args)
Notify all EndDeviceLoraPhyListener objects of the given PHY event.
Listeners m_listeners
PHY state listeners.
static TypeId GetTypeId()
Register this type.
EndDeviceLoraRegisters m_regs
High level model of LoRa chip registers.
bool IsTransmitting() const override
Whether this device is transmitting or not.
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 ...
Callback< void > RxTimeoutCallback
Type definition for a callback for when a packet reception hardware timeout expires.
~EndDeviceLoraPhy() override
Destructor.
TracedValue< State > m_state
The state this PHY is currently in.
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.
void RequestSleepMode()
Request a switch to SLEEP mode.
State
An enumeration of the possible internal states of an EndDeviceLoraPhy.
@ TX
The PHY layer is transmitting a packet.
@ 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 RegisterListener(const std::shared_ptr< EndDeviceLoraPhyListener > &listener)
Add the input listener to the list of objects to be notified of PHY-level events.
void TxFinished(Ptr< const Packet > packet) override
Internal call when transmission of a packet finishes.
RxTimeoutCallback m_rxTimeoutCallback
The callback to perform upon reception timeout.
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...
void RxTimeout()
Callback for scheduling the end of an unsuccessful timed reception attempt.
void UnregisterListener(const std::shared_ptr< EndDeviceLoraPhyListener > &listener)
Remove the input listener from the list of objects to be notified of PHY-level events.
void Sleep()
Set this PHY LoRa chip to sleep from standby after a transmission / reception.
virtual void NotifyTx(double txPowerDbm)=0
Notify listeners that the device entered TX state.
virtual void NotifyRxEnabled()=0
Notify listeners that the device entered RX_ENABLED state.
virtual void NotifyRxActive()=0
Notify listeners that the device entered RX_ACTIVE state.
virtual void NotifyStandby()=0
Notify listeners that the device entered STANDBY state.
virtual void NotifySleep()=0
Notify listeners that the device entered SLEEP state.
TxFinishedCallback m_txFinishedCallback
The callback to perform upon the end of a transmission.
Definition lora-phy.h:292
static Time GetTSym(uint8_t spreadingFactor, uint32_t bandwidthHz)
Compute the symbol time from spreading factor and bandwidth.
Definition lora-phy.cc:102
LoraPhy()
Default constructor.
Definition lora-phy.cc:199
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#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 ",...
CodingRate
Enumeration of the LoRa supported coding rates.
Definition lora-phy.h:49
IQPolarity
I/Q Polarity of LoRa transmission symbols.
Definition lora-phy.h:33
@ CR_4_5
Coding rate 4/5.
Definition lora-phy.h:50
@ UP
Uplink / Upchirp / Normal polarity.
Definition lora-phy.h:34
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
std::ostream & operator<<(std::ostream &os, const EndDeviceLoraPhy::State &state)
Overloaded operator to print the value of a EndDeviceLoraPhy::State.
Every class exported by the ns3 library is enclosed in the ns3 namespace.