1 /*!
2  * \file      LoRaMacClassB.h
3  *
4  * \brief     LoRa MAC Class B layer implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013 Semtech
16  *
17  *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
18  *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
19  *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
20  *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
21  *              embedded.connectivity.solutions===============
22  *
23  * \endcode
24  *
25  * \author    Miguel Luis ( Semtech )
26  *
27  * \author    Gregory Cristian ( Semtech )
28  *
29  * \author    Daniel Jaeckle ( STACKFORCE )
30  *
31  * \defgroup  LORAMACCLASSB LoRa MAC Class B layer implementation
32  *            This module specifies the API implementation of the LoRaMAC Class B layer.
33  *            This is a placeholder for a detailed description of the LoRaMac
34  *            layer and the supported features.
35  * \{
36  */
37 #ifndef __LORAMACCLASSB_H__
38 #define __LORAMACCLASSB_H__
39 
40 #ifdef __cplusplus
41 extern "C"
42 {
43 #endif
44 
45 #include "systime.h"
46 #include "LoRaMacTypes.h"
47 
48 /*!
49  * States of the class B beacon acquisition and tracking
50  */
51 typedef enum eBeaconState
52 {
53     /*!
54      * Initial state to acquire the beacon
55      */
56     BEACON_STATE_ACQUISITION,
57     /*!
58      * Beacon acquisition state when a time reference is available
59      */
60     BEACON_STATE_ACQUISITION_BY_TIME,
61     /*!
62      * Handles the state when the beacon reception fails
63      */
64     BEACON_STATE_TIMEOUT,
65     /*!
66      * Handles the state when the beacon was missed due to an uplink
67      */
68     BEACON_STATE_BEACON_MISSED,
69     /*!
70      * Reacquisition state which applies the algorithm to enlarge the reception
71      * windows
72      */
73     BEACON_STATE_REACQUISITION,
74     /*!
75      * The node has locked a beacon successfully
76      */
77     BEACON_STATE_LOCKED,
78     /*!
79      * The beacon state machine is stopped due to operations with higher priority
80      */
81     BEACON_STATE_HALT,
82     /*!
83      * The node currently operates in the beacon window and is idle. In this
84      * state, the temperature measurement takes place
85      */
86     BEACON_STATE_IDLE,
87     /*!
88      * The node operates in the guard time of class B
89      */
90     BEACON_STATE_GUARD,
91     /*!
92      * The node is in receive mode to lock a beacon
93      */
94     BEACON_STATE_RX,
95     /*!
96      * The nodes switches the device class
97      */
98     BEACON_STATE_LOST,
99 }BeaconState_t;
100 
101 /*!
102  * States of the class B ping slot mechanism
103  */
104 typedef enum ePingSlotState
105 {
106     /*!
107      * Calculation of the ping slot offset
108      */
109     PINGSLOT_STATE_CALC_PING_OFFSET,
110     /*!
111      * State to set the timer to open the next ping slot
112      */
113     PINGSLOT_STATE_SET_TIMER,
114     /*!
115      * The node is in idle state
116      */
117     PINGSLOT_STATE_IDLE,
118     /*!
119      * The node opens up a ping slot window
120      */
121     PINGSLOT_STATE_RX,
122 }PingSlotState_t;
123 
124 /*!
125  * Class B ping slot context structure
126  */
127 typedef struct sPingSlotContext
128 {
129 
130     /*!
131      * Ping slot length time in ms
132      */
133     uint32_t PingSlotWindow;
134     /*!
135      * Ping offset
136      */
137     uint16_t PingOffset;
138     /*!
139      * Current symbol timeout. The node enlarges this variable in case of beacon
140      * loss.
141      */
142     uint16_t SymbolTimeout;
143     /*!
144      * The multicast channel which will be enabled next.
145      */
146     MulticastCtx_t *NextMulticastChannel;
147 }PingSlotContext_t;
148 
149 
150 /*!
151  * Class B beacon context structure
152  */
153 typedef struct sBeaconContext
154 {
155     struct sBeaconCtrl
156     {
157         /*!
158          * Set if the node receives beacons
159          */
160         uint8_t BeaconMode          : 1;
161         /*!
162          * Set if the node has acquired the beacon
163          */
164         uint8_t BeaconAcquired      : 1;
165         /*!
166          * Set if a beacon delay was set for the beacon acquisition
167          */
168         uint8_t BeaconDelaySet      : 1;
169         /*!
170          * Set if a beacon channel was set for the beacon acquisition
171          */
172         uint8_t BeaconChannelSet    : 1;
173         /*!
174          * Set if beacon acquisition is pending
175          */
176         uint8_t AcquisitionPending  : 1;
177         /*!
178          * Set if the beacon state machine will be resumed
179          */
180         uint8_t ResumeBeaconing      : 1;
181     }Ctrl;
182 
183     /*!
184      * Current temperature
185      */
186     float Temperature;
187     /*!
188      * Beacon time received with the beacon frame
189      */
190     SysTime_t BeaconTime;
191     /*!
192      * Time when the last beacon was received
193      */
194     SysTime_t LastBeaconRx;
195     /*!
196      * Time when the next beacon will be received
197      */
198     SysTime_t NextBeaconRx;
199     /*!
200      * This is the time where the RX window will be opened.
201      * Its base is NextBeaconRx with temperature compensations
202      * and RX window movement.
203      */
204     TimerTime_t NextBeaconRxAdjusted;
205     /*!
206      * Current symbol timeout. The node enlarges this variable in case of beacon
207      * loss.
208      */
209     uint16_t SymbolTimeout;
210     /*!
211      * Specifies how much time the beacon window will be moved.
212      */
213     TimerTime_t BeaconWindowMovement;
214     /*!
215      * Beacon timing channel for next beacon
216      */
217     uint8_t BeaconTimingChannel;
218     /*!
219      * Delay for next beacon in ms
220      */
221     TimerTime_t BeaconTimingDelay;
222     TimerTime_t TimeStamp;
223     /*!
224      * Beacons transmit time precision determined using
225      * param field of beacon frame format.
226      */
227     SysTime_t BeaconTimePrecision;
228 }BeaconContext_t;
229 
230 /*!
231  * Data structure which contains the callbacks
232  */
233 typedef struct sLoRaMacClassBCallback
234 {
235     /*!
236      * \brief   Measures the temperature level
237      *
238      * \retval  Temperature level
239      */
240     float ( *GetTemperatureLevel )( void );
241     /*!
242      *\brief    Will be called each time a Radio IRQ is handled by the MAC
243      *          layer.
244      *
245      *\warning  Runs in a IRQ context. Should only change variables state.
246      */
247     void ( *MacProcessNotify )( void );
248 }LoRaMacClassBCallback_t;
249 
250 /*!
251  * Data structure which pointers to the properties LoRaMAC
252  */
253 typedef struct sLoRaMacClassBParams
254 {
255     /*!
256      * Pointer to the MlmeIndication structure
257      */
258     MlmeIndication_t *MlmeIndication;
259     /*!
260      * Pointer to the McpsIndication structure
261      */
262     McpsIndication_t *McpsIndication;
263     /*!
264      * Pointer to the MlmeConfirm structure
265      */
266     MlmeConfirm_t *MlmeConfirm;
267     /*!
268      * Pointer to the LoRaMacFlags structure
269      */
270     LoRaMacFlags_t *LoRaMacFlags;
271     /*!
272      * Pointer to the LoRaMac device address
273      */
274     uint32_t *LoRaMacDevAddr;
275     /*!
276      * Pointer to the LoRaMac region definition
277      */
278     LoRaMacRegion_t *LoRaMacRegion;
279     /*!
280      * Pointer to the LoRaMacParams structure
281      */
282     LoRaMacParams_t *LoRaMacParams;
283     /*!
284      * Pointer to the multicast channel list
285      */
286     MulticastCtx_t *MulticastChannels;
287     /*!
288      * Pointer to the activation type
289      */
290     ActivationType_t *NetworkActivation;
291 }LoRaMacClassBParams_t;
292 
293 /*!
294  * Signature of callback function to be called by this module when the
295  * non-volatile needs to be saved.
296  */
297 typedef void ( *LoRaMacClassBNvmEvent )( void );
298 
299 /*!
300  * \brief Initialize LoRaWAN Class B
301  *
302  * \param [IN] classBParams Information and feedback parameter
303  * \param [IN] callbacks Contains the callback which the Class B implementation needs
304  * \param [IN] nvm Pointer to an external non-volatile memory data structure.
305  */
306 void LoRaMacClassBInit( LoRaMacClassBParams_t *classBParams, LoRaMacClassBCallback_t *callbacks,
307                         LoRaMacClassBNvmData_t* nvm );
308 
309 /*!
310  * \brief Set the state of the beacon state machine
311  *
312  * \param [IN] beaconState Beacon state.
313  */
314 void LoRaMacClassBSetBeaconState( BeaconState_t beaconState );
315 
316 /*!
317  * \brief Set the state of the ping slot state machine
318  *
319  * \param [IN] pingSlotState Ping slot state.
320  */
321 void LoRaMacClassBSetPingSlotState( PingSlotState_t pingSlotState );
322 
323 /*!
324  * \brief Set the state of the multicast slot state machine
325  *
326  * \param [IN] pingSlotState multicast slot state.
327  */
328 void LoRaMacClassBSetMulticastSlotState( PingSlotState_t multicastSlotState );
329 
330 /*!
331  * \brief Verifies if an acquisition procedure is in progress
332  *
333  * \retval [true, if the acquisition is in progress; false, if not]
334  */
335 bool LoRaMacClassBIsAcquisitionInProgress( void );
336 
337 /*!
338  * \brief State machine of the Class B for beaconing
339  */
340 void LoRaMacClassBBeaconTimerEvent( void* context );
341 
342 /*!
343  * \brief State machine of the Class B for ping slots
344  */
345 void LoRaMacClassBPingSlotTimerEvent( void* context );
346 
347 /*!
348  * \brief State machine of the Class B for multicast slots
349  */
350 void LoRaMacClassBMulticastSlotTimerEvent( void* context );
351 
352 /*!
353  * \brief Receives and decodes the beacon frame
354  *
355  * \param [IN] payload Pointer to the payload
356  * \param [IN] size Size of the payload
357  * \retval [true, if the node has received a beacon; false, if not]
358  */
359 bool LoRaMacClassBRxBeacon( uint8_t *payload, uint16_t size );
360 
361 /*!
362  * \brief The function validates, if the node expects a beacon
363  *        at the current time.
364  *
365  * \retval [true, if the node expects a beacon; false, if not]
366  */
367 bool LoRaMacClassBIsBeaconExpected( void );
368 
369 /*!
370  * \brief The function validates, if the node expects a ping slot
371  *        at the current time.
372  *
373  * \retval [true, if the node expects a ping slot; false, if not]
374  */
375 bool LoRaMacClassBIsPingExpected( void );
376 
377 /*!
378  * \brief The function validates, if the node expects a multicast slot
379  *        at the current time.
380  *
381  * \retval [true, if the node expects a multicast slot; false, if not]
382  */
383 bool LoRaMacClassBIsMulticastExpected( void );
384 
385 /*!
386  * \brief Verifies if the acquisition pending bit is set
387  *
388  * \retval [true, if the bit is set; false, if not]
389  */
390 bool LoRaMacClassBIsAcquisitionPending( void );
391 
392 /*!
393  * \brief Verifies if the beacon mode active bit is set
394  *
395  * \retval [true, if the bit is set; false, if not]
396  */
397 bool LoRaMacClassBIsBeaconModeActive( void );
398 
399 /*!
400  * \brief Stops the beacon and ping slot operation
401  */
402 void LoRaMacClassBHaltBeaconing( void );
403 
404 /*!
405  * \brief Resumes the beacon and ping slot operation
406  */
407 void LoRaMacClassBResumeBeaconing( void );
408 
409 /*!
410  * \brief Sets the periodicity of the ping slots
411  *
412  * \param [IN] periodicity Periodicity
413  */
414 void LoRaMacClassBSetPingSlotInfo( uint8_t periodicity );
415 
416 /*!
417  * \brief Switches the device class
418  *
419  * \param [IN] nextClass Device class to switch to
420  *
421  * \retval LoRaMacStatus_t Status of the operation.
422  */
423 LoRaMacStatus_t LoRaMacClassBSwitchClass( DeviceClass_t nextClass );
424 
425 /*!
426  * \brief   LoRaMAC ClassB MIB-Get
427  *
428  * \details The mac information base service to get attributes of the LoRaMac
429  *          Class B layer.
430  *
431  * \param   [IN] mibRequest - MIB-GET-Request to perform. Refer to \ref MibRequestConfirm_t.
432  *
433  * \retval  LoRaMacStatus_t Status of the operation. Possible returns are:
434  *          \ref LORAMAC_STATUS_OK,
435  *          \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
436  *          \ref LORAMAC_STATUS_PARAMETER_INVALID.
437  */
438 LoRaMacStatus_t LoRaMacClassBMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
439 
440 /*!
441  * \brief   LoRaMAC Class B MIB-Set
442  *
443  * \details The mac information base service to set attributes of the LoRaMac
444  *          Class B layer.
445  *
446  * \param   [IN] mibRequest - MIB-SET-Request to perform. Refer to \ref MibRequestConfirm_t.
447  *
448  * \retval  LoRaMacStatus_t Status of the operation. Possible returns are:
449  *          \ref LORAMAC_STATUS_OK,
450  *          \ref LORAMAC_STATUS_BUSY,
451  *          \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
452  *          \ref LORAMAC_STATUS_PARAMETER_INVALID.
453  */
454 LoRaMacStatus_t LoRaMacMibClassBSetRequestConfirm( MibRequestConfirm_t *mibSet );
455 
456 /*!
457  * \brief This function handles the PING_SLOT_FREQ_ANS
458  */
459 void LoRaMacClassBPingSlotInfoAns( void );
460 
461 /*!
462  * \brief This function handles the PING_SLOT_CHANNEL_REQ
463  *
464  * \param [IN] datarate Device class to switch to
465  * \param [IN] frequency Device class to switch to
466  *
467  * \retval Status for the MAC answer.
468  */
469 uint8_t LoRaMacClassBPingSlotChannelReq( uint8_t datarate, uint32_t frequency );
470 
471 /*!
472  * \brief This function handles the BEACON_TIMING_ANS
473  *
474  * \param [IN] beaconTimingDelay The beacon timing delay
475  * \param [IN] beaconTimingChannel The beacon timing channel
476  * \param [IN] lastRxDone The time of the last frame reception
477  */
478 void LoRaMacClassBBeaconTimingAns( uint16_t beaconTimingDelay, uint8_t beaconTimingChannel, TimerTime_t lastRxDone );
479 
480 /*!
481  * \brief This function handles the ClassB DEVICE_TIME_ANS
482  */
483 void LoRaMacClassBDeviceTimeAns( void );
484 
485 /*!
486  * \brief This function handles the BEACON_FREQ_REQ
487  *
488  * \param [IN] frequency Frequency to set
489  *
490  * \retval [true, if MAC shall send an answer; false, if not]
491  */
492 bool LoRaMacClassBBeaconFreqReq( uint32_t frequency );
493 
494 /*!
495  * \brief Queries the ping slot window time
496  *
497  * \param [IN] txTimeOnAir TX time on air for the next uplink
498  *
499  * \retval Returns the time the uplink should be delayed
500  */
501 TimerTime_t LoRaMacClassBIsUplinkCollision( TimerTime_t txTimeOnAir );
502 
503 /*!
504  * \brief Stops the timers for the RX slots. This includes the
505  *        timers for ping and multicast slots.
506  */
507 void LoRaMacClassBStopRxSlots( void );
508 
509 /*!
510  * \brief Starts the timers for the RX slots. This includes the
511  *        timers for ping and multicast slots.
512  */
513 void LoRaMacClassBStartRxSlots( void );
514 
515 /*!
516  * \brief Starts the timers for the RX slots. This includes the
517  *        timers for ping and multicast slots.
518  *
519  * \param [IN] periodicity Downlink periodicity
520  *
521  * \param [IN] multicastChannel Related multicast channel
522  */
523 void LoRaMacClassBSetMulticastPeriodicity( MulticastCtx_t* multicastChannel );
524 
525 /*!
526  * \brief Sets the FPending bit status of the related downlink slot
527  *
528  * \param [IN] address Slot address, could be unicast or multicast
529  *
530  * \param [IN] fPendingSet Set to 1, if the fPending bit in the
531  *             sequence is set, otherwise 0.
532  */
533 void LoRaMacClassBSetFPendingBit( uint32_t address, uint8_t fPendingSet );
534 
535 /*!
536  * \brief Class B process function.
537  */
538 void LoRaMacClassBProcess( void );
539 
540 #ifdef __cplusplus
541 }
542 #endif
543 
544 #endif // __LORAMACCLASSB_H__
545