A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
end-device-lora-phy.h
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 * Authors: Davide Magrin <magrinda@dei.unipd.it>,
7 * Michele Luvisotto <michele.luvisotto@dei.unipd.it>
8 * Stefano Romagnolo <romagnolostefano93@gmail.com>
9 */
10
11#ifndef END_DEVICE_LORA_PHY_H
12#define END_DEVICE_LORA_PHY_H
13
14#include "lora-phy.h"
15
16#include "ns3/traced-value.h"
17
18namespace ns3
19{
20namespace lorawan
21{
22
23/**
24 * @ingroup lorawan
25 *
26 * Receive notifications about PHY internal state changes.
27 *
28 * @see EndDeviceLoraPhy::State
29 */
31{
32 public:
33 /****************************************************************
34 * This destructor is needed.
35 ****************************************************************/
36
38 {
39 }
40
41 /**
42 * Notify listeners that the device entered SLEEP state.
43 */
44 virtual void NotifySleep() = 0;
45
46 /**
47 * Notify listeners that the device entered STANDBY state.
48 */
49 virtual void NotifyStandby() = 0;
50
51 /**
52 * Notify listeners that the device entered TX state.
53 *
54 * @param txPowerDbm The nominal tx output power in dBm.
55 */
56 virtual void NotifyTx(double txPowerDbm) = 0;
57
58 /**
59 * Notify listeners that the device entered RX_ENABLED state.
60 */
61 virtual void NotifyRxEnabled() = 0;
62
63 /**
64 * Notify listeners that the device entered RX_ACTIVE state.
65 */
66 virtual void NotifyRxActive() = 0;
67};
68
69/**
70 * @ingroup lorawan
71 *
72 * Class representing a LoRa transceiver hardware state-machine of a SX1272 LoRa chip
73 * (see SX1272/73 Datasheet, Rev. 4, Jan. 2019).
74 *
75 * This class inherits the base functions of LoraPhy, like the GetTimeOnAir function, and provides
76 * Radio Abstraction Layer (RAL) functionality to parent classes. It also implements a ReceiveSingle
77 * function for external classes to start a timed reception attempt.
78 *
79 * Internally, this class features a State member variable that expresses the current hardware state
80 * of the device (SLEEP, STANDBY, TX, RX_ENABLED, RX_ACTIVE), and a structure representing the
81 * chip configurations registers. After transmission and reception, the device returns automatically
82 * to the STANDBY state. The decision of when to go into SLEEP is delegated to an external class,
83 * which can modify the state of the device through the Sleep method.
84 *
85 * Even if could appear at first glance, these states are different from the operating modes defined
86 * in the datasheet. Modes are higher level transceiver configurations that can involve multiple
87 * internal states (see RX enabled/active for instance). Here, these modes are loosely mapped to
88 * member functions for driving the PHY layer from a higher layer:
89 *
90 * - Send(): TX mode
91 * - ReceiveSingle(): RXSINGLE mode
92 * - Sleep(): SLEEP mode
93 *
94 * @todo Implementation of the RXCONTINUOUS mode
95 * @todo Implementation of the CAD mode
96 *
97 * The datasheet tells us that you can go from any mode to any other mode, but for simplicity's sake
98 * we assume that you are not able to interrupt an ongoing TX or RX window. Moreover, since it
99 * currently has no practical use, we do not allow manually switching to STANDBY mode.
100 *
101 * Transitions marked with 'a' are automatic:
102 * @verbatim
103 * +-------+
104 * +-------- | SLEEP | --------+
105 * / +-------+ \
106 * / ^ \
107 * v | v
108 * +------------+ +---------+ +----+
109 * | RX_ENABLED | <----- | STANDBY | -----> | TX |
110 * +------------+ --a--> +---------+ <--a-- +----+
111 * \ ^
112 * a \ a /
113 * v /
114 * +-----------+
115 * | RX_ACTIVE |
116 * +-----------+
117 * @endverbatim
118 *
119 * Peculiarities about the radio error model and about how errors are supposed to be handled during
120 * transmission and reception are left to classes extending this one, like SimpleEndDeviceLoraPhy or
121 * SpectrumEndDeviceLoraPhy. These classes need to implement the pure virtual member function Send,
122 * StartReceive and EndReceive.
123 */
125{
126 public:
127 /**
128 * Type definition for a callback for when a packet reception hardware timeout expires.
129 *
130 * This callback can be set by an upper layer that wishes to be informed of reception timeout
131 * events.
132 */
134
135 /**
136 * An enumeration of the possible internal states of an EndDeviceLoraPhy. It makes
137 * sense to define a state for End Devices since there's only one demodulator which can either
138 * transmit, receive, be idle or go in a deep sleep state. See the description of the states for
139 * more details on the possible transitions of the PHY state-machine.
140 *
141 * @note Even if could appear at first glance, these states are different from the operating
142 * modes defined in the datasheet. Modes are higher level transceiver configurations that can
143 * involve multiple internal states (see RX enabled/active for instance).
144 */
145 enum class State
146 {
147 /**
148 * The PHY layer is in low-power sleep state. No reception or transmission can happen.
149 * The only reachable states from this one are TX and RX_ENABLED.
150 */
152
153 /**
154 * The PHY layer is in standby mode. This is the default in-between state where only the
155 * chip's components common to both RX and TX are powered on. All other states are reachable
156 * from this one with the exception of RX_ACTIVE.
157 */
159
160 /**
161 * The PHY layer is transmitting a packet. During the transmission, the device is busy and
162 * cannot receive any packet or send any additional packet. The only reachable state from
163 * this one is STANDBY, and the switch should be automatically handled by the chip.
164 */
166
167 /**
168 * The PHY layer is listening to the channel for a valid transmission preamble. While the
169 * device in this process, it is busy and transmission is not possible. The states
170 * reachable from this one are RX_ACTIVE or STANDBY.
171 *
172 * If a premble is found, the PHY transitions to RX_ACTIVE and starts receiving a packet.
173 * Otherwise, the PHY remains in this state until manually reset to STANDBY.
174 *
175 * In RXSINGLE mode an interrupt to STANDBY is usually scheduled after a certain amount of
176 * time to create a reception window.
177 *
178 * @todo In RXCONTINUOUS mode, this must be done manually by the user.
179 */
181
182 /**
183 * The PHY layer is actively receiving a transmission after locking onto a preamble. While
184 * the device in this process, it is busy and transmission is not possible. The states
185 * reachable from this one are either STANDBY or RX_ENABLED, and the switch to either should
186 * be automatically handled by the chip depending on the mode (RXSINGLE or RXCONTINUOUS).
187 *
188 * In RXSINGLE mode, the PHY is reset to STANDBY after reception ends.
189 *
190 * @todo In RXCONTINUOUS mode, the PHY goes back to RX_ENABLED instead.
191 */
193
194 // NOTE: When extending/updating, please update operator<< accordingly.
195 };
196
197 /**
198 * Register this type.
199 * @return The object TypeId.
200 */
201 static TypeId GetTypeId();
202
203 EndDeviceLoraPhy(); //!< Default constructor
204 ~EndDeviceLoraPhy() override; //!< Destructor
205
206 static const double SENSITIVITY[6]; //!< The sensitivity vector of this device to different SFs
207
208 // Forward LoraPhy's pure virtual function
209 void Send(Ptr<Packet> packet,
210 uint32_t frequencyHz,
211 IQPolarity iqPolarity,
212 const LoraTxParameters& txParams,
213 double txPowerDbm) override = 0;
214
215 // Forward LoraPhy's pure virtual function
217 uint32_t frequencyHz,
218 IQPolarity iqPolarity,
219 uint8_t spreadingFactor,
220 double rxPowerDbm,
221 Time duration) override = 0;
222
223 // Implementation of LoraPhy's pure virtual function
224 bool IsTransmitting() const override;
225
226 // Implementation of LoraPhy's pure virtual function
227 bool IsOnFrequency(uint32_t frequencyHz) const override;
228
229 /**
230 * Return the internal state this end device is currently in.
231 *
232 * @return The internal state.
233 */
234 State GetState();
235
236 /**
237 * Set this PHY LoRa chip to sleep from standby after a transmission / reception.
238 */
239 void Sleep();
240
241 /**
242 * This function starts a reception attempt that will time-out if no transmission preamble is
243 * detected. Input parameters are written in the PHY state and used for reception.
244 *
245 * @note Basic LoRa transceivers as the one modeled here are only able to listen for a distinct
246 * spreading factor on a single frequency channel; all other transmissions will be discarded.
247 *
248 * @param frequencyHz Expected central frequency [Hz] of the incoming transmission
249 * @param iqPolarity Whether to expect an uplink or downlink signal
250 * @param spreadingFactor Expected Spreading Factor (SF) of the incoming transmission
251 * @param bandwidthHz Expected bandwidth [Hz] of the incoming transmission
252 * @param symbNumTimeout The reception timeout duration in number of symbols
253 * @param rxTimeoutCallback Optional callback executed on reception timeout
254 */
255 void ReceiveSingle(uint32_t frequencyHz,
256 IQPolarity iqPolarity,
257 uint8_t spreadingFactor,
258 uint32_t bandwidthHz,
259 uint8_t symbNumTimeout,
260 RxTimeoutCallback rxTimeoutCallback);
261
262 /**
263 * Add the input listener to the list of objects to be notified of PHY-level
264 * events.
265 *
266 * @param listener The new listener.
267 */
268 void RegisterListener(const std::shared_ptr<EndDeviceLoraPhyListener>& listener);
269
270 /**
271 * Remove the input listener from the list of objects to be notified of
272 * PHY-level events.
273 *
274 * @param listener The listener to be unregistered.
275 */
276 void UnregisterListener(const std::shared_ptr<EndDeviceLoraPhyListener>& listener);
277
278 protected:
279 /**
280 * Parameters affecting the internal PHY transmission / reception of a packet,
281 * normally stored in the chip registers.
282 *
283 * Some parameters have slightly different meaning depending on the follow-up mode activated.
284 *
285 * For transmission, the symbol number timeout has no effect.
286 *
287 * @todo For reception, the payload length represents the maximum number of packet Bytes that
288 * are accepted. The the premble length represents the minimum number of preamble symbols to
289 * expect from the transmitter (if unknown, it should be set to max). With implicit header mode,
290 * the payload length, coding rate and CRC validation must be also set explicitly.
291 *
292 * @note Currently, only frequencyHz, bandwidthHz, iqPolarity, spreadingFactor, symbNumTimeout
293 * and txPowerDbm play a stateful role during device operation. The rest is implemented for
294 * future expansions.
295 */
297 {
298 // Modulation parameters
299 uint8_t spreadingFactor = 7; //!< Symbol Spreading Factor (SF)
300 uint32_t bandwidthHz = 125'000; //!< Transmission bandwidth in Hz
301 CodingRate codingRate = CodingRate::CR_4_5; //!< Transmission coding rate
302 bool lowDataRateOptimize = false; //!< Low Data Rate Optimization (mandated for SF11/12)
303 // PHY packet parameters
304 uint16_t preambleLenSymb = 8; //!< Number of symbols in the packet preamble
305 uint8_t payloadLenBytes = 1; //!< Number of Bytes the packet payload
306 bool implicitHeader = false; //!< Whether to use implicit header mode
307 bool crcEnabled = true; //!< Whether Cyclic Redundancy Check (CRC) is enabled
308 IQPolarity iqPolarity = IQPolarity::UP; //!< Whether to process an uplink or downlink signal
309 // Base parameters
310 uint32_t frequencyHz = 868'100'000; //!< The transmission central frequency [Hz]
311 int8_t txPowerDbm = 14; //!< The output power [dBm] to use for packet transmission
312 uint8_t syncWord = 0x34; //!< The LoRa sync. word (0x34 is reserved for LoRaWAN)
313 uint8_t symbNumTimeout = 8; //!< The reception timeout duration in number of symbols
314 };
315
316 // Implementation of LoraPhy's pure virtual function
317 void TxFinished(Ptr<const Packet> packet) override;
318
319 // Radio Abstraction Layer
320
321 /**
322 * Request a switch to SLEEP mode.
323 *
324 * This only has an effect when in STANDBY state.
325 */
326 void RequestSleepMode();
327
328 /**
329 * This function puts the PHY in transmission mode. Parent classes must take care of scheduling
330 * TxFinished() to automatically revert to STANDBY.
331 *
332 * @warning Before calling this function, parent classes must ensure that the device is in
333 * SLEEP or STANDBY mode: Registers can only be accessed when in these modes.
334 */
335 void RequestTxMode();
336
337 /**
338 * This function reads RX parameters from the internal registers of the PHY hardware and begins
339 * a reception attempt that will time-out if no transmission preamble is detected, automatically
340 * reverting to STANDBY. Parent classes must take care of calling DoStartReceive() in case the
341 * chip actually starts receiving from the channel during the reception attempt.
342 *
343 * @warning Before calling this function, parent classes must ensure that the device is in
344 * SLEEP or STANDBY mode: Registers can only be accessed when in these modes.
345 */
346 void RequestRxSingleMode();
347
348 /**
349 * This function should be called by parent classes to signal that the PHY is starting to
350 * demodulate a transmission. Internally, it cancels the RX attempt interrupt timeout and
351 * switches from RX_ENABLED to RX_ACTIVE. Parent classes must take care of calling
352 * DoEndReceive() before invoking any upper layer callback (RxOk, RxFailed)
353 *
354 * @warning Before calling this function, parent classes must ensure that the device is in
355 * the RX_ENABLED state
356 */
357 void DoStartReceive();
358
359 /**
360 * This function should be called by parent classes to signal that the PHY is finishing to
361 * demodulate a transmission. Internally, it switches from RX_ACTIVE to STANDBY
362 *
363 * @warning Before calling this function, parent classes must ensure that the device is in
364 * the RX_ACTIVE state
365 */
366 void DoEndReceive();
367
368 /**
369 * Trace source for when a packet is lost because it was transmitted on a frequency different
370 * from the one this EndDeviceLoraPhy was configured to listen on.
371 */
373
374 /**
375 * Trace source for when a packet is lost because it was transmitted with a different I/Q
376 * polarity (uplink or downlink) from the one this EndDeviceLoraPhy was configured to listen on.
377 */
379
380 /**
381 * Trace source for when a packet is lost because it was using a spreading factor different from
382 * the one this EndDeviceLoraPhy was configured to listen for.
383 */
385
386 EndDeviceLoraRegisters m_regs; //!< High level model of LoRa chip registers
387
388 private:
389 /**
390 * typedef for a list of EndDeviceLoraPhyListeners. We use weak pointers so that unregistering a
391 * listener is not necessary to delete a listener (reference count is not incremented by weak
392 * pointers).
393 */
394 typedef std::list<std::weak_ptr<EndDeviceLoraPhyListener>> Listeners;
395
396 // Forward LoraPhy's pure virtual function
398
399 /**
400 * Callback for scheduling the end of an unsuccessful timed reception attempt.
401 *
402 * This is meant to model the hardware interrupt of real LoRa transceivers.
403 */
404 void RxTimeout();
405
406 // Unsafe handles for hardware state switching
407
408 /**
409 * Switch to the SLEEP state.
410 *
411 * This fails if not in STANDBY state.
412 */
413 void SwitchToSleep();
414
415 /**
416 * Switch to the STANDBY state.
417 *
418 * @note This function is reserved for automatically switching to STANDBY after TX/RX
419 *
420 * This fails if in SLEEP state or already in STANDBY state.
421 */
422 void SwitchToStandBy();
423
424 /**
425 * Switch to the TX state.
426 *
427 * This fails if not in SLEEP or STANDBY state.
428 */
429 void SwitchToTx();
430
431 /**
432 * Switch to the RX_ENABLED state.
433 *
434 * This fails if not in SLEEP or STANDBY state.
435 */
436 void SwitchToRxEnabled();
437
438 /**
439 * Update the RX state to RX_ACTIVE on preamble lock.
440 *
441 * @note This function will cancel any scheduled RX timeout event
442 *
443 * This fails if not in RX_ENABLED state.
444 */
445 void SwitchToRxActive();
446
447 /**
448 * Notify all EndDeviceLoraPhyListener objects of the given PHY event.
449 *
450 * @tparam FUNC \deduced Member function type
451 * @tparam Ts \deduced Function argument types
452 * @param f the member function to invoke
453 * @param args arguments to pass to the member function
454 */
455 template <typename FUNC, typename... Ts>
456 void NotifyListeners(FUNC f, Ts&&... args);
457
458 /**
459 * The callback to perform upon reception timeout. In reality, this is an hardware interrupt.
460 */
462
463 TracedValue<State> m_state; //!< The state this PHY is currently in.
464 EventId m_rxTimeoutEvent; //!< Event for timed switch from RX_ENABLED to STANDBY
465
466 Listeners m_listeners; //!< PHY state listeners
467};
468
469/**
470 * Overloaded operator to print the value of a EndDeviceLoraPhy::State.
471 *
472 * @param os The output stream
473 * @param state The enum value of the PHY state
474 * @return The output stream with text value of the PHY state
475 */
476std::ostream& operator<<(std::ostream& os, const EndDeviceLoraPhy::State& state);
477
478template <typename FUNC, typename... Ts>
479void
481{
482 // NS_LOG_FUNCTION(this); // why doesn't logging work? see wifi-phy-state-helper.h
483 // A notification to a PHY listener may involve the addition and/or removal of a PHY listener,
484 // thus modifying the list we are iterating over. This is dangerous, so ensure that we iterate
485 // over a copy of the list of PHY listeners. The copied list contains shared pointers to the PHY
486 // listeners to prevent them from being deleted.
487 std::list<std::shared_ptr<EndDeviceLoraPhyListener>> listeners;
488 std::transform(m_listeners.cbegin(),
489 m_listeners.cend(),
490 std::back_inserter(listeners),
491 [](auto&& listener) { return listener.lock(); });
492
493 for (const auto& listener : listeners)
494 {
495 if (listener)
496 {
497 std::invoke(f, listener, std::forward<Ts>(args)...);
498 }
499 }
500}
501
502} // namespace lorawan
503} // namespace ns3
504
505#endif /* END_DEVICE_LORA_PHY_H */
Callback template class.
Definition callback.h:428
An identifier for simulation events.
Definition event-id.h:45
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
Forward calls to a chain of Callback.
Trace classes with value semantics.
a unique identifier for an interface.
Definition type-id.h:50
void StartReceive(Ptr< Packet > packet, uint32_t frequencyHz, IQPolarity iqPolarity, uint8_t spreadingFactor, double rxPowerDbm, Time duration) override=0
Start receiving a packet.
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.
void Send(Ptr< Packet > packet, uint32_t frequencyHz, IQPolarity iqPolarity, const LoraTxParameters &txParams, double txPowerDbm) override=0
Instruct the PHY to send a packet according to some parameters.
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...
void EndReceive(Ptr< Packet > packet, Ptr< LoraInterferenceHelper::Event > event) override=0
Finish reception of a packet.
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.
std::list< std::weak_ptr< EndDeviceLoraPhyListener > > Listeners
typedef for a list of EndDeviceLoraPhyListeners.
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.
Receive notifications about PHY internal state changes.
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.
LoraPhy()
Default constructor.
Definition lora-phy.cc:199
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
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.
Parameters affecting the internal PHY transmission / reception of a packet, normally stored in the ch...
bool crcEnabled
Whether Cyclic Redundancy Check (CRC) is enabled.
IQPolarity iqPolarity
Whether to process an uplink or downlink signal.
uint16_t preambleLenSymb
Number of symbols in the packet preamble.
int8_t txPowerDbm
The output power [dBm] to use for packet transmission.
uint8_t symbNumTimeout
The reception timeout duration in number of symbols.
bool implicitHeader
Whether to use implicit header mode.
uint8_t payloadLenBytes
Number of Bytes the packet payload.
uint32_t frequencyHz
The transmission central frequency [Hz].
bool lowDataRateOptimize
Low Data Rate Optimization (mandated for SF11/12).
Structure to collect all parameters that are used to compute the duration of a packet (excluding payl...
Definition lora-phy.h:73