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