Damian Gabino / LoRaWAN-lib

Fork of LoRaWAN-lib-v1_0_1 by Uttam Bhat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LoRaMac.cpp Source File

LoRaMac.cpp

00001 /*
00002  / _____)             _              | |
00003 ( (____  _____ ____ _| |_ _____  ____| |__
00004  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00005  _____) ) ____| | | || |_| ____( (___| | | |
00006 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00007     (C)2013 Semtech
00008  ___ _____ _   ___ _  _____ ___  ___  ___ ___
00009 / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
00010 \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
00011 |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
00012 embedded.connectivity.solutions===============
00013 
00014 Description: LoRa MAC layer implementation
00015 
00016 License: Revised BSD License, see LICENSE.TXT file include in the project
00017 
00018 Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
00019 */
00020 #include "board.h"
00021 
00022 #include "LoRaMacCrypto.h"
00023 #include "LoRaMac.h"
00024 #include "LoRaMacTest.h"
00025 
00026 /*!
00027  * Maximum PHY layer payload size
00028  */
00029 #define LORAMAC_PHY_MAXPAYLOAD                      255
00030 
00031 /*!
00032  * Maximum MAC commands buffer size
00033  */
00034 #define LORA_MAC_COMMAND_MAX_LENGTH                 15
00035 
00036 /*!
00037  * FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
00038  * in RxWindowSetup function.
00039  * Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD
00040  */
00041 #define LORA_MAC_FRMPAYLOAD_OVERHEAD                13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
00042 
00043 /*!
00044  * Device IEEE EUI
00045  */
00046 static uint8_t *LoRaMacDevEui;
00047 
00048 /*!
00049  * Application IEEE EUI
00050  */
00051 static uint8_t *LoRaMacAppEui;
00052 
00053 /*!
00054  * AES encryption/decryption cipher application key
00055  */
00056 static uint8_t *LoRaMacAppKey;
00057 
00058 /*!
00059  * AES encryption/decryption cipher network session key
00060  */
00061 static uint8_t LoRaMacNwkSKey[] =
00062 {
00063     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00064     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00065 };
00066 
00067 /*!
00068  * AES encryption/decryption cipher application session key
00069  */
00070 static uint8_t LoRaMacAppSKey[] =
00071 {
00072     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00073     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00074 };
00075 
00076 /*!
00077  * Device nonce is a random value extracted by issuing a sequence of RSSI
00078  * measurements
00079  */
00080 static uint16_t LoRaMacDevNonce;
00081 
00082 /*!
00083  * Network ID ( 3 bytes )
00084  */
00085 static uint32_t LoRaMacNetID;
00086 
00087 /*!
00088  * Mote Address
00089  */
00090 static uint32_t LoRaMacDevAddr;
00091 
00092 /*!
00093  * Multicast channels linked list
00094  */
00095 static MulticastParams_t  *MulticastChannels = NULL;
00096 
00097 /*!
00098  * Actual device class
00099  */
00100 static DeviceClass_t  LoRaMacDeviceClass;
00101 
00102 /*!
00103  * Indicates if the node is connected to a private or public network
00104  */
00105 static bool PublicNetwork;
00106 
00107 /*!
00108  * Indicates if the node supports repeaters
00109  */
00110 static bool RepeaterSupport;
00111 
00112 /*!
00113  * Buffer containing the data to be sent or received.
00114  */
00115 static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];
00116 
00117 /*!
00118  * Length of packet in LoRaMacBuffer
00119  */
00120 static uint16_t LoRaMacBufferPktLen = 0;
00121 
00122 /*!
00123  * Buffer containing the upper layer data.
00124  */
00125 static uint8_t LoRaMacPayload[LORAMAC_PHY_MAXPAYLOAD];
00126 static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
00127 
00128 /*!
00129  * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
00130  * Only the 16 LSB bits are sent
00131  */
00132 static uint32_t UpLinkCounter = 1;
00133 
00134 /*!
00135  * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
00136  * Only the 16 LSB bits are received
00137  */
00138 static uint32_t DownLinkCounter = 0;
00139 
00140 /*!
00141  * IsPacketCounterFixed enables the MIC field tests by fixing the
00142  * UpLinkCounter value
00143  */
00144 static bool IsUpLinkCounterFixed = false;
00145 
00146 /*!
00147  * Used for test purposes. Disables the opening of the reception windows.
00148  */
00149 static bool IsRxWindowsEnabled = true;
00150 
00151 /*!
00152  * Indicates if the MAC layer has already joined a network.
00153  */
00154 static bool IsLoRaMacNetworkJoined = false;
00155 
00156 /*!
00157  * LoRaMac ADR control status
00158  */
00159 static bool AdrCtrlOn = false;
00160 
00161 /*!
00162  * Counts the number of missed ADR acknowledgements
00163  */
00164 static uint32_t AdrAckCounter = 0;
00165 
00166 /*!
00167  * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
00168  * if the nodes needs to manage the server acknowledgement.
00169  */
00170 static bool NodeAckRequested = false;
00171 
00172 /*!
00173  * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
00174  * if the ACK bit must be set for the next transmission
00175  */
00176 static bool SrvAckRequested = false;
00177 
00178 /*!
00179  * Indicates if the MAC layer wants to send MAC commands
00180  */
00181 static bool MacCommandsInNextTx = false;
00182 
00183 /*!
00184  * Contains the current MacCommandsBuffer index
00185  */
00186 static uint8_t MacCommandsBufferIndex = 0;
00187 
00188 /*!
00189  * Buffer containing the MAC layer commands
00190  */
00191 static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
00192 
00193 #if defined( USE_BAND_433 )
00194 /*!
00195  * Data rates table definition
00196  */
00197 const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
00198 
00199 /*!
00200  * Maximum payload with respect to the datarate index. Cannot operate with repeater.
00201  */
00202 const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
00203 
00204 /*!
00205  * Maximum payload with respect to the datarate index. Can operate with repeater.
00206  */
00207 const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
00208 
00209 /*!
00210  * Tx output powers table definition
00211  */
00212 const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
00213 
00214 /*!
00215  * LoRaMac bands
00216  */
00217 static Band_t  Bands[LORA_MAX_NB_BANDS] =
00218 {
00219     BAND0,
00220 };
00221 
00222 /*!
00223  * LoRaMAC channels
00224  */
00225 static ChannelParams_t  Channels[LORA_MAX_NB_CHANNELS] =
00226 {
00227     LC1,
00228     LC2,
00229     LC3,
00230 };
00231 #elif defined( USE_BAND_780 )
00232 /*!
00233  * Data rates table definition
00234  */
00235 const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
00236 
00237 /*!
00238  * Maximum payload with respect to the datarate index. Cannot operate with repeater.
00239  */
00240 const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
00241 
00242 /*!
00243  * Maximum payload with respect to the datarate index. Can operate with repeater.
00244  */
00245 const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
00246 
00247 /*!
00248  * Tx output powers table definition
00249  */
00250 const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
00251 
00252 /*!
00253  * LoRaMac bands
00254  */
00255 static Band_t  Bands[LORA_MAX_NB_BANDS] =
00256 {
00257     BAND0,
00258 };
00259 
00260 /*!
00261  * LoRaMAC channels
00262  */
00263 static ChannelParams_t  Channels[LORA_MAX_NB_CHANNELS] =
00264 {
00265     LC1,
00266     LC2,
00267     LC3,
00268 };
00269 #elif defined( USE_BAND_868 )
00270 /*!
00271  * Data rates table definition
00272  */
00273 const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
00274 
00275 /*!
00276  * Maximum payload with respect to the datarate index. Cannot operate with repeater.
00277  */
00278 const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
00279 
00280 /*!
00281  * Maximum payload with respect to the datarate index. Can operate with repeater.
00282  */
00283 const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
00284 
00285 /*!
00286  * Tx output powers table definition
00287  */
00288 const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
00289 
00290 /*!
00291  * LoRaMac bands
00292  */
00293 static Band_t  Bands[LORA_MAX_NB_BANDS] =
00294 {
00295     BAND0,
00296     BAND1,
00297     BAND2,
00298     BAND3,
00299     BAND4,
00300 };
00301 
00302 /*!
00303  * LoRaMAC channels
00304  */
00305 static ChannelParams_t  Channels[LORA_MAX_NB_CHANNELS] =
00306 {
00307     LC1,
00308     LC2,
00309     LC3,
00310 };
00311 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
00312 /*!
00313  * Data rates table definition
00314  */
00315 const uint8_t Datarates[]  = { 10, 9, 8,  7,  8,  0,  0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
00316 
00317 /*!
00318  * Up/Down link data rates offset definition
00319  */
00320 const int8_t datarateOffsets[16][4] =
00321 {
00322     { DR_10, DR_9 , DR_8 , DR_8  }, // DR_0
00323     { DR_11, DR_10, DR_9 , DR_8  }, // DR_1
00324     { DR_12, DR_11, DR_10, DR_9  }, // DR_2
00325     { DR_13, DR_12, DR_11, DR_10 }, // DR_3
00326     { DR_13, DR_13, DR_12, DR_11 }, // DR_4
00327     { 0xFF , 0xFF , 0xFF , 0xFF  },
00328     { 0xFF , 0xFF , 0xFF , 0xFF  },
00329     { 0xFF , 0xFF , 0xFF , 0xFF  },
00330     { DR_8 , DR_8 , DR_8 , DR_8  },
00331     { DR_9 , DR_8 , DR_8 , DR_8  },
00332     { DR_10, DR_9 , DR_8 , DR_8  },
00333     { DR_11, DR_10, DR_9 , DR_8  },
00334     { DR_12, DR_11, DR_10, DR_9  },
00335     { DR_13, DR_12, DR_11, DR_10 },
00336     { 0xFF , 0xFF , 0xFF , 0xFF  },
00337     { 0xFF , 0xFF , 0xFF , 0xFF  },
00338 };
00339 
00340 /*!
00341  * Maximum payload with respect to the datarate index. Cannot operate with repeater.
00342  */
00343 const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 129, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
00344 
00345 /*!
00346  * Maximum payload with respect to the datarate index. Can operate with repeater.
00347  */
00348 const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 129, 242, 242, 0, 0, 0, 33, 103, 222, 222, 222, 222, 0, 0 };
00349 
00350 /*!
00351  * Tx output powers table definition
00352  */
00353 const int8_t TxPowers[]    = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };
00354 
00355 /*!
00356  * LoRaMac bands
00357  */
00358 static Band_t  Bands[LORA_MAX_NB_BANDS] =
00359 {
00360     BAND0,
00361 };
00362 
00363 /*!
00364  * LoRaMAC channels
00365  */
00366 static ChannelParams_t  Channels[LORA_MAX_NB_CHANNELS];
00367 
00368 /*!
00369  * Contains the channels which remain to be applied.
00370  */
00371 static uint16_t ChannelsMaskRemaining[6];
00372 #else
00373     #error "Please define a frequency band in the compiler options."
00374 #endif
00375 
00376 /*!
00377  * LoRaMAC 2nd reception window settings
00378  */
00379 static Rx2ChannelParams_t  Rx2Channel = RX_WND_2_CHANNEL;
00380 
00381 /*!
00382  * Datarate offset between uplink and downlink on first window
00383  */
00384 static uint8_t Rx1DrOffset = 0;
00385 
00386 /*!
00387  * Mask indicating which channels are enabled
00388  */
00389 static uint16_t ChannelsMask[6];
00390 
00391 /*!
00392  * Channels Tx output power
00393  */
00394 static int8_t ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
00395 
00396 /*!
00397  * Channels datarate
00398  */
00399 static int8_t ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
00400 
00401 /*!
00402  * Channels default datarate
00403  */
00404 static int8_t ChannelsDefaultDatarate = LORAMAC_DEFAULT_DATARATE;
00405 
00406 /*!
00407  * Number of uplink messages repetitions [1:15] (unconfirmed messages only)
00408  */
00409 static uint8_t ChannelsNbRep = 1;
00410 
00411 /*!
00412  * Uplink messages repetitions counter
00413  */
00414 static uint8_t ChannelsNbRepCounter = 0;
00415 
00416 /*!
00417  * Maximum duty cycle
00418  * \remark Possibility to shutdown the device.
00419  */
00420 static uint8_t MaxDCycle = 0;
00421 
00422 /*!
00423  * Aggregated duty cycle management
00424  */
00425 static uint16_t AggregatedDCycle;
00426 static TimerTime_t AggregatedLastTxDoneTime;
00427 static TimerTime_t AggregatedTimeOff;
00428 
00429 /*!
00430  * Enables/Disables duty cycle management (Test only)
00431  */
00432 static bool DutyCycleOn;
00433 
00434 /*!
00435  * Current channel index
00436  */
00437 static uint8_t Channel;
00438 
00439 static uint8_t LastTxChannel;
00440 
00441 /*!
00442  * LoRaMac internal states
00443  */
00444 enum eLoRaMacState
00445 {
00446     MAC_IDLE          = 0x00000000,
00447     MAC_TX_RUNNING    = 0x00000001,
00448     MAC_RX            = 0x00000002,
00449     MAC_ACK_REQ       = 0x00000004,
00450     MAC_ACK_RETRY     = 0x00000008,
00451     MAC_TX_DELAYED    = 0x00000010,
00452     MAC_TX_CONFIG     = 0x00000020,
00453     MAC_RX_ABORT      = 0x00000040,
00454 };
00455 
00456 /*!
00457  * LoRaMac internal state
00458  */
00459 uint32_t LoRaMacState = MAC_IDLE;
00460 
00461 /*!
00462  * LoRaMac timer used to check the LoRaMacState (runs every second)
00463  */
00464 static TimerEvent_t MacStateCheckTimer;
00465 
00466 /*!
00467  * LoRaMac upper layer event functions
00468  */
00469 static LoRaMacPrimitives_t  *LoRaMacPrimitives;
00470 
00471 /*!
00472  * LoRaMac upper layer callback functions
00473  */
00474 static LoRaMacCallback_t *LoRaMacCallbacks;
00475 
00476 /*!
00477  * Radio events function pointer
00478  */
00479 static RadioEvents_t RadioEvents;
00480 
00481 /*!
00482  * LoRaMac duty cycle delayed Tx timer
00483  */
00484 static TimerEvent_t TxDelayedTimer;
00485 
00486 /*!
00487  * LoRaMac reception windows timers
00488  */
00489 static TimerEvent_t RxWindowTimer1;
00490 static TimerEvent_t RxWindowTimer2;
00491 
00492 /*!
00493  * LoRaMac reception windows delay from end of Tx
00494  */
00495 static uint32_t ReceiveDelay1;
00496 static uint32_t ReceiveDelay2;
00497 static uint32_t JoinAcceptDelay1;
00498 static uint32_t JoinAcceptDelay2;
00499 
00500 /*!
00501  * LoRaMac reception windows delay
00502  * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
00503  *         join frame  : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
00504  */
00505 static uint32_t RxWindow1Delay;
00506 static uint32_t RxWindow2Delay;
00507 
00508 /*!
00509  * LoRaMac maximum time a reception window stays open
00510  */
00511 static uint32_t MaxRxWindow;
00512 
00513 /*!
00514  * Acknowledge timeout timer. Used for packet retransmissions.
00515  */
00516 static TimerEvent_t AckTimeoutTimer;
00517 
00518 /*!
00519  * Number of trials to get a frame acknowledged
00520  */
00521 static uint8_t AckTimeoutRetries = 1;
00522 
00523 /*!
00524  * Number of trials to get a frame acknowledged
00525  */
00526 static uint8_t AckTimeoutRetriesCounter = 1;
00527 
00528 /*!
00529  * Indicates if the AckTimeout timer has expired or not
00530  */
00531 static bool AckTimeoutRetry = false;
00532 
00533 /*!
00534  * Last transmission time on air
00535  */
00536 TimerTime_t TxTimeOnAir = 0;
00537 
00538 /*!
00539  * Structure to hold an MCPS indication data.
00540  */
00541 static McpsIndication_t  McpsIndication;
00542 
00543 /*!
00544  * Structure to hold MCPS confirm data.
00545  */
00546 static McpsConfirm_t  McpsConfirm;
00547 
00548 /*!
00549  * Structure to hold MLME confirm data.
00550  */
00551 static MlmeConfirm_t  MlmeConfirm;
00552 
00553 /*!
00554  * Holds the current rx window slot
00555  */
00556 static uint8_t RxSlot = 0;
00557 
00558 /*!
00559  * LoRaMac tx/rx operation state
00560  */
00561 LoRaMacFlags_t  LoRaMacFlags;
00562 
00563 /*!
00564  * \brief Function to be executed on Radio Tx Done event
00565  */
00566 static void OnRadioTxDone( void );
00567 
00568 /*!
00569  * \brief This function prepares the MAC to abort the execution of function
00570  *        OnRadioRxDone in case of a reception error.
00571  */
00572 static void PrepareRxDoneAbort( void );
00573 
00574 /*!
00575  * \brief Function to be executed on Radio Rx Done event
00576  */
00577 static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
00578 
00579 /*!
00580  * \brief Function executed on Radio Tx Timeout event
00581  */
00582 static void OnRadioTxTimeout( void );
00583 
00584 /*!
00585  * \brief Function executed on Radio Rx error event
00586  */
00587 static void OnRadioRxError( void );
00588 
00589 /*!
00590  * \brief Function executed on Radio Rx Timeout event
00591  */
00592 static void OnRadioRxTimeout( void );
00593 
00594 /*!
00595  * \brief Function executed on Resend Frame timer event.
00596  */
00597 static void OnMacStateCheckTimerEvent( void );
00598 
00599 /*!
00600  * \brief Function executed on duty cycle delayed Tx  timer event
00601  */
00602 static void OnTxDelayedTimerEvent( void );
00603 
00604 /*!
00605  * \brief Function executed on first Rx window timer event
00606  */
00607 static void OnRxWindow1TimerEvent( void );
00608 
00609 /*!
00610  * \brief Function executed on second Rx window timer event
00611  */
00612 static void OnRxWindow2TimerEvent( void );
00613 
00614 /*!
00615  * \brief Function executed on AckTimeout timer event
00616  */
00617 static void OnAckTimeoutTimerEvent( void );
00618 
00619 /*!
00620  * \brief Searches and set the next random available channel
00621  *
00622  * \param [OUT] Time to wait for the next transmission according to the duty
00623  *              cycle.
00624  *
00625  * \retval status  Function status [1: OK, 0: Unable to find a channel on the
00626  *                                  current datarate]
00627  */
00628 static bool SetNextChannel( TimerTime_t* time );
00629 
00630 /*!
00631  * \brief Sets the network to public or private. Updates the sync byte.
00632  *
00633  * \param [IN] enable if true, it enables a public network
00634  */
00635 static void SetPublicNetwork( bool enable );
00636 
00637 /*!
00638  * \brief Initializes and opens the reception window
00639  *
00640  * \param [IN] freq window channel frequency
00641  * \param [IN] datarate window channel datarate
00642  * \param [IN] bandwidth window channel bandwidth
00643  * \param [IN] timeout window channel timeout
00644  */
00645 static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
00646 
00647 /*!
00648  * \brief Adds a new MAC command to be sent.
00649  *
00650  * \Remark MAC layer internal function
00651  *
00652  * \param [in] cmd MAC command to be added
00653  *                 [MOTE_MAC_LINK_CHECK_REQ,
00654  *                  MOTE_MAC_LINK_ADR_ANS,
00655  *                  MOTE_MAC_DUTY_CYCLE_ANS,
00656  *                  MOTE_MAC_RX2_PARAM_SET_ANS,
00657  *                  MOTE_MAC_DEV_STATUS_ANS
00658  *                  MOTE_MAC_NEW_CHANNEL_ANS]
00659  * \param [in] p1  1st parameter ( optional depends on the command )
00660  * \param [in] p2  2nd parameter ( optional depends on the command )
00661  *
00662  * \retval status  Function status [0: OK, 1: Unknown command, 2: Buffer full]
00663  */
00664 static LoRaMacStatus_t  AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );
00665 
00666 /*!
00667  * \brief Validates if the payload fits into the frame, taking the datarate
00668  *        into account.
00669  *
00670  * \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
00671  *
00672  * \param lenN Length of the application payload. The length depends on the
00673  *             datarate and is region specific
00674  *
00675  * \param datarate Current datarate
00676  *
00677  * \param fOptsLen Length of the fOpts field
00678  *
00679  * \retval [false: payload does not fit into the frame, true: payload fits into
00680  *          the frame]
00681  */
00682 static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
00683 
00684 /*!
00685  * \brief Counts the number of bits in a mask.
00686  *
00687  * \param [IN] mask A mask from which the function counts the active bits.
00688  * \param [IN] nbBits The number of bits to check.
00689  *
00690  * \retval Number of enabled bits in the mask.
00691  */
00692 static uint8_t CountBits( uint16_t mask, uint8_t nbBits );
00693 
00694 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
00695 /*!
00696  * \brief Counts the number of enabled 125 kHz channels in the channel mask.
00697  *        This function can only be applied to US915 band.
00698  *
00699  * \param [IN] channelsMask Pointer to the first element of the channel mask
00700  *
00701  * \retval Number of enabled channels in the channel mask
00702  */
00703 static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask );
00704 
00705 #if defined( USE_BAND_915_HYBRID )
00706 /*!
00707  * \brief Validates the correctness of the channel mask for US915, hybrid mode.
00708  *
00709  * \param [IN] mask Block definition to set.
00710  * \param [OUT] channelsMask Pointer to the first element of the channel mask
00711  */
00712 static void ReenableChannels( uint16_t mask, uint16_t* channelMask );
00713 
00714 /*!
00715  * \brief Validates the correctness of the channel mask for US915, hybrid mode.
00716  *
00717  * \param [IN] channelsMask Pointer to the first element of the channel mask
00718  *
00719  * \retval [true: channel mask correct, false: channel mask not correct]
00720  */
00721 static bool ValidateChannelMask( uint16_t* channelMask );
00722 #endif
00723 
00724 #endif
00725 
00726 /*!
00727  * \brief Limits the Tx power according to the number of enabled channels
00728  *
00729  * \retval Returns the maximum valid tx power
00730  */
00731 static int8_t LimitTxPower( int8_t txPower );
00732 
00733 /*!
00734  * \brief Verifies, if a value is in a given range.
00735  *
00736  * \param value Value to verify, if it is in range
00737  *
00738  * \param min Minimum possible value
00739  *
00740  * \param max Maximum possible value
00741  *
00742  * \retval Returns the maximum valid tx power
00743  */
00744 static bool ValueInRange( int8_t value, int8_t min, int8_t max );
00745 
00746 /*!
00747  * \brief Calculates the next datarate to set, when ADR is on or off
00748  *
00749  * \param [IN] adrEnabled Specify whether ADR is on or off
00750  *
00751  * \param [IN] updateChannelMask Set to true, if the channel masks shall be updated
00752  *
00753  * \param [OUT] datarateOut Reports the datarate which will be used next
00754  *
00755  * \retval Returns the state of ADR ack request
00756  */
00757 static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut );
00758 
00759 /*!
00760  * \brief Disables channel in a specified channel mask
00761  *
00762  * \param [IN] id - Id of the channel
00763  *
00764  * \param [IN] mask - Pointer to the channel mask to edit
00765  *
00766  * \retval [true, if disable was successful, false if not]
00767  */
00768 static bool DisableChannelInMask( uint8_t id, uint16_t* mask );
00769 
00770 /*!
00771  * \brief Decodes MAC commands in the fOpts field and in the payload
00772  */
00773 static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr );
00774 
00775 /*!
00776  * \brief LoRaMAC layer generic send frame
00777  *
00778  * \param [IN] macHdr      MAC header field
00779  * \param [IN] fPort       MAC payload port
00780  * \param [IN] fBuffer     MAC data buffer to be sent
00781  * \param [IN] fBufferSize MAC data buffer size
00782  * \retval status          Status of the operation.
00783  */
00784 LoRaMacStatus_t  Send( LoRaMacHeader_t  *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
00785 
00786 /*!
00787  * \brief LoRaMAC layer frame buffer initialization
00788  *
00789  * \param [IN] macHdr      MAC header field
00790  * \param [IN] fCtrl       MAC frame control field
00791  * \param [IN] fOpts       MAC commands buffer
00792  * \param [IN] fPort       MAC payload port
00793  * \param [IN] fBuffer     MAC data buffer to be sent
00794  * \param [IN] fBufferSize MAC data buffer size
00795  * \retval status          Status of the operation.
00796  */
00797 LoRaMacStatus_t  PrepareFrame( LoRaMacHeader_t  *macHdr, LoRaMacFrameCtrl_t  *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
00798 
00799 /*
00800  * \brief Schedules the frame according to the duty cycle
00801  *
00802  * \retval Status of the operation
00803  */
00804 static LoRaMacStatus_t  ScheduleTx( void );
00805 
00806 /*
00807  * \brief Calculates the back-off time for the band of a channel.
00808  *
00809  * \param [IN] channel     The last Tx channel index
00810  */
00811 static void CalculateBackOff( uint8_t channel );
00812 
00813 /*!
00814  * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
00815  *
00816  * \remark PrepareFrame must be called at least once before calling this
00817  *         function.
00818  *
00819  * \param [IN] channel     Channel parameters
00820  * \retval status          Status of the operation.
00821  */
00822 LoRaMacStatus_t  SendFrameOnChannel( ChannelParams_t  channel );
00823 
00824 
00825 
00826 static void OnRadioTxDone( void )
00827 {
00828     TimerTime_t curTime = TimerGetCurrentTime( );
00829     if( LoRaMacDeviceClass != CLASS_C  )
00830     {
00831         Radio.Sleep( );
00832     }
00833     else
00834     {
00835         OnRxWindow2TimerEvent( );
00836     }
00837 
00838     // Store last Tx channel
00839     LastTxChannel = Channel;
00840     // Update last tx done time for the current channel
00841     Bands[Channels[LastTxChannel].Band ].LastTxDoneTime  = curTime;
00842     // Update Aggregated last tx done time
00843     AggregatedLastTxDoneTime = curTime;
00844 
00845     if( IsRxWindowsEnabled == true )
00846     {
00847         TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
00848         TimerStart( &RxWindowTimer1 );
00849         if( LoRaMacDeviceClass != CLASS_C  )
00850         {
00851             TimerSetValue( &RxWindowTimer2, RxWindow2Delay );
00852             TimerStart( &RxWindowTimer2 );
00853         }
00854         if( ( LoRaMacDeviceClass == CLASS_C  ) || ( NodeAckRequested == true ) )
00855         {
00856             TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + ACK_TIMEOUT +
00857                                              randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) );
00858             TimerStart( &AckTimeoutTimer );
00859         }
00860     }
00861     else
00862     {
00863         McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK ;
00864         MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
00865 
00866         if( LoRaMacFlags.Value  == 0 )
00867         {
00868             LoRaMacFlags.Bits.McpsReq  = 1;
00869         }
00870         LoRaMacFlags.Bits.MacDone  = 1;
00871     }
00872 
00873     if( NodeAckRequested == false )
00874     {
00875         McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK ;
00876         ChannelsNbRepCounter++;
00877     }
00878 }
00879 
00880 static void PrepareRxDoneAbort( void )
00881 {
00882     LoRaMacState |= MAC_RX_ABORT;
00883 
00884     if( NodeAckRequested )
00885     {
00886         OnAckTimeoutTimerEvent( );
00887     }
00888 
00889     if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C  ) )
00890     {
00891         OnRxWindow2TimerEvent( );
00892     }
00893 
00894     LoRaMacFlags.Bits.McpsInd  = 1;
00895     LoRaMacFlags.Bits.MacDone  = 1;
00896 
00897     // Trig OnMacCheckTimerEvent call as soon as possible
00898     TimerSetValue( &MacStateCheckTimer, 1000 );
00899     TimerStart( &MacStateCheckTimer );
00900 }
00901 
00902 static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
00903 {
00904     LoRaMacHeader_t  macHdr;
00905     LoRaMacFrameCtrl_t  fCtrl;
00906     bool skipIndication = false;
00907 
00908     uint8_t pktHeaderLen = 0;
00909     uint32_t address = 0;
00910     uint8_t appPayloadStartIndex = 0;
00911     uint8_t port = 0xFF;
00912     uint8_t frameLen = 0;
00913     uint32_t mic = 0;
00914     uint32_t micRx = 0;
00915 
00916     uint16_t sequenceCounter = 0;
00917     uint16_t sequenceCounterPrev = 0;
00918     uint16_t sequenceCounterDiff = 0;
00919     uint32_t downLinkCounter = 0;
00920 
00921     MulticastParams_t  *curMulticastParams = NULL;
00922     uint8_t *nwkSKey = LoRaMacNwkSKey;
00923     uint8_t *appSKey = LoRaMacAppSKey;
00924 
00925     uint8_t multicast = 0;
00926 
00927     bool isMicOk = false;
00928 
00929     McpsConfirm.AckReceived = false;
00930     McpsIndication.Rssi  = rssi;
00931     McpsIndication.Snr  = snr;
00932     McpsIndication.RxSlot  = RxSlot;
00933     McpsIndication.Port  = 0;
00934     McpsIndication.Multicast  = 0;
00935     McpsIndication.FramePending  = 0;
00936     McpsIndication.Buffer  = NULL;
00937     McpsIndication.BufferSize  = 0;
00938     McpsIndication.RxData  = false;
00939     McpsIndication.AckReceived  = false;
00940     McpsIndication.DownLinkCounter  = 0;
00941     McpsIndication.McpsIndication  = MCPS_UNCONFIRMED ;
00942 
00943     if( LoRaMacDeviceClass != CLASS_C  )
00944     {
00945         Radio.Sleep( );
00946     }
00947     TimerStop( &RxWindowTimer2 );
00948 
00949     macHdr.Value  = payload[pktHeaderLen++];
00950 
00951     switch( macHdr.Bits.MType  )
00952     {
00953         case FRAME_TYPE_JOIN_ACCEPT :
00954             if( IsLoRaMacNetworkJoined == true )
00955             {
00956                 break;
00957             }
00958             LoRaMacJoinDecrypt ( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
00959 
00960             LoRaMacRxPayload[0] = macHdr.Value ;
00961 
00962             LoRaMacJoinComputeMic ( LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic );
00963 
00964             micRx |= ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
00965             micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8 );
00966             micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
00967             micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );
00968 
00969             if( micRx == mic )
00970             {
00971                 LoRaMacJoinComputeSKeys ( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
00972 
00973                 LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
00974                 LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
00975                 LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
00976 
00977                 LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
00978                 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
00979                 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
00980                 LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
00981 
00982                 // DLSettings
00983                 Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
00984                 Rx2Channel.Datarate  = LoRaMacRxPayload[11] & 0x0F;
00985 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
00986                 /*
00987                  * WARNING: To be removed once Semtech server implementation
00988                  *          is corrected.
00989                  */
00990                 if( Rx2Channel.Datarate  == DR_3 )
00991                 {
00992                     Rx2Channel.Datarate  = DR_8;
00993                 }
00994 #endif
00995                 // RxDelay
00996                 ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
00997                 if( ReceiveDelay1 == 0 )
00998                 {
00999                     ReceiveDelay1 = 1;
01000                 }
01001                 ReceiveDelay1 *= 1e6;
01002                 ReceiveDelay2 = ReceiveDelay1 + 1e6;
01003 
01004 #if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
01005                 //CFList
01006                 if( ( size - 1 ) > 16 )
01007                 {
01008                     ChannelParams_t  param;
01009                     param.DrRange .Value  = ( DR_5 << 4 ) | DR_0;
01010 
01011                     LoRaMacState |= MAC_TX_CONFIG;
01012                     for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 )
01013                     {
01014                         param.Frequency  = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100;
01015                         LoRaMacChannelAdd( i, param );
01016                     }
01017                     LoRaMacState &= ~MAC_TX_CONFIG;
01018                 }
01019 #endif
01020                 MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_OK ;
01021                 IsLoRaMacNetworkJoined = true;
01022                 ChannelsDatarate = ChannelsDefaultDatarate;
01023             }
01024             else
01025             {
01026                 MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL ;
01027             }
01028             break;
01029         case FRAME_TYPE_DATA_CONFIRMED_DOWN :
01030         case FRAME_TYPE_DATA_UNCONFIRMED_DOWN :
01031             {
01032                 address = payload[pktHeaderLen++];
01033                 address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
01034                 address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
01035                 address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );
01036 
01037                 if( address != LoRaMacDevAddr )
01038                 {
01039                     curMulticastParams = MulticastChannels;
01040                     while( curMulticastParams != NULL )
01041                     {
01042                         if( address == curMulticastParams->Address  )
01043                         {
01044                             multicast = 1;
01045                             nwkSKey = curMulticastParams->NwkSKey ;
01046                             appSKey = curMulticastParams->AppSKey ;
01047                             downLinkCounter = curMulticastParams->DownLinkCounter ;
01048                             break;
01049                         }
01050                         curMulticastParams = curMulticastParams->Next ;
01051                     }
01052                     if( multicast == 0 )
01053                     {
01054                         // We are not the destination of this frame.
01055                         McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL ;
01056                         PrepareRxDoneAbort( );
01057                         return;
01058                     }
01059                 }
01060                 else
01061                 {
01062                     multicast = 0;
01063                     nwkSKey = LoRaMacNwkSKey;
01064                     appSKey = LoRaMacAppSKey;
01065                     downLinkCounter = DownLinkCounter;
01066                 }
01067 
01068                 fCtrl.Value  = payload[pktHeaderLen++];
01069 
01070                 sequenceCounter = ( uint16_t )payload[pktHeaderLen++];
01071                 sequenceCounter |= ( uint16_t )payload[pktHeaderLen++] << 8;
01072 
01073                 appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen ;
01074 
01075                 micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
01076                 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 1] << 8 );
01077                 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 2] << 16 );
01078                 micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 3] << 24 );
01079 
01080                 sequenceCounterPrev = ( uint16_t )downLinkCounter;
01081                 sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev );
01082 
01083                 if( sequenceCounterDiff < ( 1 << 15 ) )
01084                 {
01085                     downLinkCounter += sequenceCounterDiff;
01086                     LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
01087                     if( micRx == mic )
01088                     {
01089                         isMicOk = true;
01090                     }
01091                 }
01092                 else
01093                 {
01094                     // check for sequence roll-over
01095                     uint32_t  downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff;
01096                     LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic );
01097                     if( micRx == mic )
01098                     {
01099                         isMicOk = true;
01100                         downLinkCounter = downLinkCounterTmp;
01101                     }
01102                 }
01103 
01104                 // Check for a the maximum allowed counter difference
01105                 if( sequenceCounterDiff >= MAX_FCNT_GAP )
01106                 {
01107                     McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS ;
01108                     McpsIndication.DownLinkCounter  = downLinkCounter;
01109                     PrepareRxDoneAbort( );
01110                     return;
01111                 }
01112 
01113                 if( isMicOk == true )
01114                 {
01115                     McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_OK ;
01116                     McpsIndication.Multicast  = multicast;
01117                     McpsIndication.FramePending  = fCtrl.Bits.FPending ;
01118                     McpsIndication.Buffer  = NULL;
01119                     McpsIndication.BufferSize  = 0;
01120                     McpsIndication.DownLinkCounter  = downLinkCounter;
01121 
01122                     McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK ;
01123 
01124                     AdrAckCounter = 0;
01125 
01126                     // Update 32 bits downlink counter
01127                     if( multicast == 1 )
01128                     {
01129                         McpsIndication.McpsIndication  = MCPS_MULTICAST ;
01130 
01131                         if( ( curMulticastParams->DownLinkCounter  == downLinkCounter ) &&
01132                             ( curMulticastParams->DownLinkCounter  != 0 ) )
01133                         {
01134                             McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
01135                             McpsIndication.DownLinkCounter  = downLinkCounter;
01136                             PrepareRxDoneAbort( );
01137                             return;
01138                         }
01139                         curMulticastParams->DownLinkCounter  = downLinkCounter;
01140                     }
01141                     else
01142                     {
01143                         if( macHdr.Bits.MType  == FRAME_TYPE_DATA_CONFIRMED_DOWN  )
01144                         {
01145                             SrvAckRequested = true;
01146                             McpsIndication.McpsIndication  = MCPS_CONFIRMED ;
01147 
01148                             if( ( DownLinkCounter == downLinkCounter ) &&
01149                                 ( DownLinkCounter != 0 ) )
01150                             {
01151                                 // Duplicated confirmed downlink. Skip indication.
01152                                 skipIndication = true;
01153                             }
01154                         }
01155                         else
01156                         {
01157                             SrvAckRequested = false;
01158                             McpsIndication.McpsIndication  = MCPS_UNCONFIRMED ;
01159 
01160                             if( ( DownLinkCounter == downLinkCounter ) &&
01161                                 ( DownLinkCounter != 0 ) )
01162                             {
01163                                 McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED ;
01164                                 McpsIndication.DownLinkCounter  = downLinkCounter;
01165                                 PrepareRxDoneAbort( );
01166                                 return;
01167                             }
01168                         }
01169                         DownLinkCounter = downLinkCounter;
01170                     }
01171 
01172                     // Check if the frame is an acknowledgement
01173                     if( fCtrl.Bits.Ack  == 1 )
01174                     {
01175                         McpsConfirm.AckReceived = true;
01176                         McpsIndication.AckReceived  = true;
01177 
01178                         // Stop the AckTimeout timer as no more retransmissions
01179                         // are needed.
01180                         TimerStop( &AckTimeoutTimer );
01181                     }
01182                     else
01183                     {
01184                         McpsConfirm.AckReceived = false;
01185 
01186                         if( AckTimeoutRetriesCounter > AckTimeoutRetries )
01187                         {
01188                             // Stop the AckTimeout timer as no more retransmissions
01189                             // are needed.
01190                             TimerStop( &AckTimeoutTimer );
01191                         }
01192                     }
01193 
01194                     if( fCtrl.Bits.FOptsLen  > 0 )
01195                     {
01196                         // Decode Options field MAC commands
01197                         ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
01198                     }
01199                     if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
01200                     {
01201                         port = payload[appPayloadStartIndex++];
01202                         frameLen = ( size - 4 ) - appPayloadStartIndex;
01203 
01204                         McpsIndication.Port  = port;
01205 
01206                         if( port == 0 )
01207                         {
01208                             LoRaMacPayloadDecrypt ( payload + appPayloadStartIndex,
01209                                                    frameLen,
01210                                                    nwkSKey,
01211                                                    address,
01212                                                    DOWN_LINK,
01213                                                    downLinkCounter,
01214                                                    LoRaMacRxPayload );
01215 
01216                             // Decode frame payload MAC commands
01217                             ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
01218                         }
01219                         else
01220                         {
01221                             LoRaMacPayloadDecrypt ( payload + appPayloadStartIndex,
01222                                                    frameLen,
01223                                                    appSKey,
01224                                                    address,
01225                                                    DOWN_LINK,
01226                                                    downLinkCounter,
01227                                                    LoRaMacRxPayload );
01228 
01229                             if( skipIndication == false )
01230                             {
01231                                 McpsIndication.Buffer  = LoRaMacRxPayload;
01232                                 McpsIndication.BufferSize  = frameLen;
01233                                 McpsIndication.RxData  = true;
01234                             }
01235                         }
01236                     }
01237                     if( skipIndication == false )
01238                     {
01239                         LoRaMacFlags.Bits.McpsInd  = 1;
01240                     }
01241                 }
01242                 else
01243                 {
01244                     McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL ;
01245 
01246                     PrepareRxDoneAbort( );
01247                     return;
01248                 }
01249             }
01250             break;
01251         case FRAME_TYPE_PROPRIETARY :
01252             {
01253                 memcpy1( LoRaMacRxPayload, &payload[pktHeaderLen], size );
01254 
01255                 McpsIndication.McpsIndication  = MCPS_PROPRIETARY ;
01256                 McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_OK ;
01257                 McpsIndication.Buffer  = LoRaMacRxPayload;
01258                 McpsIndication.BufferSize  = size - pktHeaderLen;
01259 
01260                 LoRaMacFlags.Bits.McpsInd  = 1;
01261                 break;
01262             }
01263         default:
01264             McpsIndication.Status  = LORAMAC_EVENT_INFO_STATUS_ERROR ;
01265             PrepareRxDoneAbort( );
01266             break;
01267     }
01268 
01269     if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C  ) )
01270     {
01271         OnRxWindow2TimerEvent( );
01272     }
01273     LoRaMacFlags.Bits.MacDone  = 1;
01274 
01275     // Trig OnMacCheckTimerEvent call as soon as possible
01276     TimerSetValue( &MacStateCheckTimer, 1000 );
01277     TimerStart( &MacStateCheckTimer );
01278 }
01279 
01280 static void OnRadioTxTimeout( void )
01281 {
01282     if( LoRaMacDeviceClass != CLASS_C  )
01283     {
01284         Radio.Sleep( );
01285     }
01286     else
01287     {
01288         OnRxWindow2TimerEvent( );
01289     }
01290 
01291     McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
01292     MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ;
01293     LoRaMacFlags.Bits.MacDone  = 1;
01294 }
01295 
01296 static void OnRadioRxError( void )
01297 {
01298     if( LoRaMacDeviceClass != CLASS_C  )
01299     {
01300         Radio.Sleep( );
01301     }
01302     else
01303     {
01304         OnRxWindow2TimerEvent( );
01305     }
01306 
01307     if( RxSlot == 1 )
01308     {
01309         if( NodeAckRequested == true )
01310         {
01311             McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
01312         }
01313         MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR ;
01314         LoRaMacFlags.Bits.MacDone  = 1;
01315     }
01316 }
01317 
01318 static void OnRadioRxTimeout( void )
01319 {
01320     if( LoRaMacDeviceClass != CLASS_C  )
01321     {
01322         Radio.Sleep( );
01323     }
01324     else
01325     {
01326         OnRxWindow2TimerEvent( );
01327     }
01328 
01329     if( RxSlot == 1 )
01330     {
01331         if( NodeAckRequested == true )
01332         {
01333             McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
01334         }
01335         MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT ;
01336         LoRaMacFlags.Bits.MacDone  = 1;
01337     }
01338 }
01339 
01340 static void OnMacStateCheckTimerEvent( void )
01341 {
01342     TimerStop( &MacStateCheckTimer );
01343     bool txTimeout = false;
01344 
01345     if( LoRaMacFlags.Bits.MacDone  == 1 )
01346     {
01347         if( ( LoRaMacState & MAC_RX_ABORT ) == MAC_RX_ABORT )
01348         {
01349             LoRaMacState &= ~MAC_RX_ABORT;
01350             LoRaMacState &= ~MAC_TX_RUNNING;
01351         }
01352 
01353         if( ( LoRaMacFlags.Bits.MlmeReq  == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq  == 1 ) ) )
01354         {
01355             if( ( McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT  ) ||
01356                 ( MlmeConfirm.Status  == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT  ) )
01357             {
01358                 // Stop transmit cycle due to tx timeout.
01359                 LoRaMacState &= ~MAC_TX_RUNNING;
01360                 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
01361                 McpsConfirm.AckReceived = false;
01362                 McpsConfirm.TxTimeOnAir = 0;
01363                 txTimeout = true;
01364             }
01365         }
01366 
01367         if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
01368         {
01369             if( LoRaMacFlags.Bits.MlmeReq  == 1 )
01370             {
01371                 if( MlmeConfirm.MlmeRequest  == MLME_JOIN  )
01372                 {
01373                     if( MlmeConfirm.Status  == LORAMAC_EVENT_INFO_STATUS_OK  )
01374                     {
01375                         UpLinkCounter = 0;
01376                     }
01377                     // Join messages aren't repeated automatically
01378                     ChannelsNbRepCounter = ChannelsNbRep;
01379                 }
01380             }
01381             if( ( LoRaMacFlags.Bits.MlmeReq  == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq  == 1 ) ) )
01382             {
01383                 if( ( ChannelsNbRepCounter >= ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd  == 1 ) )
01384                 {
01385                     ChannelsNbRepCounter = 0;
01386 
01387                     AdrAckCounter++;
01388                     if( IsUpLinkCounterFixed == false )
01389                     {
01390                         UpLinkCounter++;
01391                     }
01392 
01393                     LoRaMacState &= ~MAC_TX_RUNNING;
01394                 }
01395                 else
01396                 {
01397                     LoRaMacFlags.Bits.MacDone  = 0;
01398                     // Sends the same frame again
01399                     ScheduleTx( );
01400                 }
01401             }
01402         }
01403 
01404         if( LoRaMacFlags.Bits.McpsInd  == 1 )
01405         {
01406             if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
01407             {
01408                 AckTimeoutRetry = false;
01409                 NodeAckRequested = false;
01410                 if( IsUpLinkCounterFixed == false )
01411                 {
01412                     UpLinkCounter++;
01413                 }
01414                 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
01415 
01416                 LoRaMacState &= ~MAC_TX_RUNNING;
01417             }
01418         }
01419 
01420         if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & MAC_TX_DELAYED ) == 0 ) )
01421         {
01422             AckTimeoutRetry = false;
01423             if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
01424             {
01425                 AckTimeoutRetriesCounter++;
01426 
01427                 if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
01428                 {
01429                     ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
01430                 }
01431                 LoRaMacFlags.Bits.MacDone  = 0;
01432 
01433                 // Sends the same frame again
01434                 ScheduleTx( );
01435             }
01436             else
01437             {
01438 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
01439                 // Re-enable default channels LC1, LC2, LC3
01440                 ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
01441 #elif defined( USE_BAND_915 )
01442                 // Re-enable default channels
01443                 ChannelsMask[0] = 0xFFFF;
01444                 ChannelsMask[1] = 0xFFFF;
01445                 ChannelsMask[2] = 0xFFFF;
01446                 ChannelsMask[3] = 0xFFFF;
01447                 ChannelsMask[4] = 0x00FF;
01448                 ChannelsMask[5] = 0x0000;
01449 #elif defined( USE_BAND_915_HYBRID )
01450                 // Re-enable default channels
01451                 ReenableChannels( ChannelsMask[4], ChannelsMask );
01452 #else
01453     #error "Please define a frequency band in the compiler options."
01454 #endif
01455                 LoRaMacState &= ~MAC_TX_RUNNING;
01456 
01457                 NodeAckRequested = false;
01458                 McpsConfirm.AckReceived = false;
01459                 McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
01460                 if( IsUpLinkCounterFixed == false )
01461                 {
01462                     UpLinkCounter++;
01463                 }
01464             }
01465         }
01466     }
01467     // Handle reception for Class B and Class C
01468     if( ( LoRaMacState & MAC_RX ) == MAC_RX )
01469     {
01470         LoRaMacState &= ~MAC_RX;
01471     }
01472     if( LoRaMacState == MAC_IDLE )
01473     {
01474         if( LoRaMacFlags.Bits.McpsReq  == 1 )
01475         {
01476             LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm );
01477             LoRaMacFlags.Bits.McpsReq  = 0;
01478         }
01479 
01480         if( LoRaMacFlags.Bits.MlmeReq  == 1 )
01481         {
01482             LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm );
01483             LoRaMacFlags.Bits.MlmeReq  = 0;
01484         }
01485 
01486         LoRaMacFlags.Bits.MacDone  = 0;
01487     }
01488     else
01489     {
01490         // Operation not finished restart timer
01491         TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
01492         TimerStart( &MacStateCheckTimer );
01493     }
01494 
01495     if( LoRaMacFlags.Bits.McpsInd  == 1 )
01496     {
01497         LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
01498         LoRaMacFlags.Bits.McpsInd  = 0;
01499     }
01500 }
01501 
01502 static void OnTxDelayedTimerEvent( void )
01503 {
01504     TimerStop( &TxDelayedTimer );
01505     LoRaMacState &= ~MAC_TX_DELAYED;
01506 
01507     ScheduleTx( );
01508 }
01509 
01510 static void OnRxWindow1TimerEvent( void )
01511 {
01512     uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
01513     int8_t datarate = 0;
01514     uint32_t bandwidth = 0; // LoRa 125 kHz
01515 
01516     TimerStop( &RxWindowTimer1 );
01517     RxSlot = 0;
01518 
01519     if( LoRaMacDeviceClass == CLASS_C  )
01520     {
01521         Radio.Standby( );
01522     }
01523 
01524 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
01525     datarate = ChannelsDatarate - Rx1DrOffset;
01526     if( datarate < 0 )
01527     {
01528         datarate = DR_0;
01529     }
01530 
01531     // For higher datarates, we increase the number of symbols generating a Rx Timeout
01532     if( ( datarate == DR_3 ) || ( datarate == DR_4 ) )
01533     { // DR_4, DR_3
01534         symbTimeout = 8;
01535     }
01536     else if( datarate == DR_5 )
01537     {
01538         symbTimeout = 10;
01539     }
01540     else if( datarate == DR_6 )
01541     {// LoRa 250 kHz
01542         bandwidth  = 1;
01543         symbTimeout = 14;
01544     }
01545     RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
01546 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
01547     datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset];
01548     if( datarate < 0 )
01549     {
01550         datarate = DR_0;
01551     }
01552     // For higher datarates, we increase the number of symbols generating a Rx Timeout
01553     switch( datarate )
01554     {
01555         case DR_0:       // SF10 - BW125
01556             symbTimeout = 5;
01557             break;
01558 
01559         case DR_1:       // SF9  - BW125
01560         case DR_2:       // SF8  - BW125
01561         case DR_8:       // SF12 - BW500
01562         case DR_9:       // SF11 - BW500
01563         case DR_10:      // SF10 - BW500
01564             symbTimeout = 8;
01565             break;
01566 
01567         case DR_3:       // SF7  - BW125
01568         case DR_11:      // SF9  - BW500
01569             symbTimeout = 10;
01570             break;
01571 
01572         case DR_4:       // SF8  - BW500
01573         case DR_12:      // SF8  - BW500
01574             symbTimeout = 14;
01575             break;
01576 
01577         case DR_13:      // SF7  - BW500
01578             symbTimeout = 16;
01579             break;
01580         default:
01581             break;
01582     }
01583     if( datarate >= DR_4 )
01584     {// LoRa 500 kHz
01585         bandwidth  = 2;
01586     }
01587     RxWindowSetup( 923.3e6 + ( Channel % 8 ) * 600e3, datarate, bandwidth, symbTimeout, false );
01588 #else
01589     #error "Please define a frequency band in the compiler options."
01590 #endif
01591 }
01592 
01593 static void OnRxWindow2TimerEvent( void )
01594 {
01595     uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
01596     uint32_t bandwidth = 0; // LoRa 125 kHz
01597 
01598     TimerStop( &RxWindowTimer2 );
01599     RxSlot = 1;
01600 
01601 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
01602     // For higher datarates, we increase the number of symbols generating a Rx Timeout
01603     if( ( Rx2Channel.Datarate  == DR_3 ) || ( Rx2Channel.Datarate  == DR_4 ) )
01604     { // DR_4, DR_3
01605         symbTimeout = 8;
01606     }
01607     else if( Rx2Channel.Datarate  == DR_5 )
01608     {
01609         symbTimeout = 10;
01610     }
01611     else if( Rx2Channel.Datarate  == DR_6 )
01612     {// LoRa 250 kHz
01613         bandwidth  = 1;
01614         symbTimeout = 14;
01615     }
01616 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
01617     // For higher datarates, we increase the number of symbols generating a Rx Timeout
01618     switch( Rx2Channel.Datarate  )
01619     {
01620         case DR_0:       // SF10 - BW125
01621             symbTimeout = 5;
01622             break;
01623 
01624         case DR_1:       // SF9  - BW125
01625         case DR_2:       // SF8  - BW125
01626         case DR_8:       // SF12 - BW500
01627         case DR_9:       // SF11 - BW500
01628         case DR_10:      // SF10 - BW500
01629             symbTimeout = 8;
01630             break;
01631 
01632         case DR_3:       // SF7  - BW125
01633         case DR_11:      // SF9  - BW500
01634             symbTimeout = 10;
01635             break;
01636 
01637         case DR_4:       // SF8  - BW500
01638         case DR_12:      // SF8  - BW500
01639             symbTimeout = 14;
01640             break;
01641 
01642         case DR_13:      // SF7  - BW500
01643             symbTimeout = 16;
01644             break;
01645         default:
01646             break;
01647     }
01648     if( Rx2Channel.Datarate  >= DR_4 )
01649     {// LoRa 500 kHz
01650         bandwidth  = 2;
01651     }
01652 #else
01653     #error "Please define a frequency band in the compiler options."
01654 #endif
01655     if( LoRaMacDeviceClass != CLASS_C  )
01656     {
01657         RxWindowSetup( Rx2Channel.Frequency , Rx2Channel.Datarate , bandwidth, symbTimeout, false );
01658     }
01659     else
01660     {
01661         RxWindowSetup( Rx2Channel.Frequency , Rx2Channel.Datarate , bandwidth, symbTimeout, true );
01662     }
01663 }
01664 
01665 static void OnAckTimeoutTimerEvent( void )
01666 {
01667     TimerStop( &AckTimeoutTimer );
01668 
01669     if( NodeAckRequested == true )
01670     {
01671         AckTimeoutRetry = true;
01672         LoRaMacState &= ~MAC_ACK_REQ;
01673     }
01674     if( LoRaMacDeviceClass == CLASS_C  )
01675     {
01676         LoRaMacFlags.Bits.MacDone  = 1;
01677     }
01678 }
01679 
01680 static bool SetNextChannel( TimerTime_t* time )
01681 {
01682     uint8_t nbEnabledChannels = 0;
01683     uint8_t delayTx = 0;
01684     uint8_t enabledChannels[LORA_MAX_NB_CHANNELS];
01685     TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
01686 
01687     memset1( enabledChannels, 0, LORA_MAX_NB_CHANNELS );
01688 
01689 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
01690     if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 )
01691     { // Restore default channels
01692         memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 8 );
01693     }
01694     if( ( ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) )
01695     { // Make sure, that the channels are activated
01696         ChannelsMaskRemaining[4] = ChannelsMask[4];
01697     }
01698 #else
01699     if( CountBits( ChannelsMask[0], 16 ) == 0 )
01700     {
01701         // Re-enable default channels, if no channel is enabled
01702         ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
01703     }
01704 #endif
01705 
01706     // Update Aggregated duty cycle
01707     if( AggregatedTimeOff <= TimerGetElapsedTime( AggregatedLastTxDoneTime ) )
01708     {
01709         AggregatedTimeOff = 0;
01710 
01711         // Update bands Time OFF
01712         for( uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++ )
01713         {
01714             if( DutyCycleOn == true )
01715             {
01716                 if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) )
01717                 {
01718                     Bands[i].TimeOff  = 0;
01719                 }
01720                 if( Bands[i].TimeOff != 0 )
01721                 {
01722                     nextTxDelay = MIN( Bands[i].TimeOff -
01723                                        TimerGetElapsedTime( Bands[i].LastTxDoneTime ),
01724                                        nextTxDelay );
01725                 }
01726             }
01727             else
01728             {
01729                 nextTxDelay = 0;
01730                 Bands[i].TimeOff  = 0;
01731             }
01732         }
01733 
01734         // Search how many channels are enabled
01735         for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
01736         {
01737             for( uint8_t j = 0; j < 16; j++ )
01738             {
01739 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
01740                 if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 )
01741 #else
01742                 if( ( ChannelsMask[k] & ( 1 << j ) ) != 0 )
01743 #endif
01744                 {
01745                     if( Channels[i + j].Frequency == 0 )
01746                     { // Check if the channel is enabled
01747                         continue;
01748                     }
01749 #if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
01750                     if( IsLoRaMacNetworkJoined == false )
01751                     {
01752                         if( ( JOIN_CHANNELS & ( 1 << j ) ) == 0 )
01753                         {
01754                             continue;
01755                         }
01756                     }
01757 #endif
01758                     if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) &&
01759                           ( ChannelsDatarate <= Channels[i + j].DrRange .Fields.Max  ) ) == false )
01760                     { // Check if the current channel selection supports the given datarate
01761                         continue;
01762                     }
01763                     if( Bands[Channels[i + j].Band].TimeOff > 0 )
01764                     { // Check if the band is available for transmission
01765                         delayTx++;
01766                         continue;
01767                     }
01768                     enabledChannels[nbEnabledChannels++] = i + j;
01769                 }
01770             }
01771         }
01772     }
01773     else
01774     {
01775         delayTx++;
01776         nextTxDelay = AggregatedTimeOff - TimerGetElapsedTime( AggregatedLastTxDoneTime );
01777     }
01778 
01779     if( nbEnabledChannels > 0 )
01780     {
01781         Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
01782 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
01783         if( Channel < ( LORA_MAX_NB_CHANNELS - 8 ) )
01784         {
01785             DisableChannelInMask( Channel, ChannelsMaskRemaining );
01786         }
01787 #endif
01788         *time = 0;
01789         return true;
01790     }
01791     else
01792     {
01793         if( delayTx > 0 )
01794         {
01795             // Delay transmission due to AggregatedTimeOff or to a band time off
01796             *time = nextTxDelay;
01797             return true;
01798         }
01799         // Datarate not supported by any channel
01800         *time = 0;
01801         return false;
01802     }
01803 }
01804 
01805 static void SetPublicNetwork( bool enable )
01806 {
01807     PublicNetwork = enable;
01808     Radio.SetModem( MODEM_LORA );
01809     if( PublicNetwork == true )
01810     {
01811         // Change LoRa modem SyncWord
01812         Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
01813     }
01814     else
01815     {
01816         // Change LoRa modem SyncWord
01817         Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
01818     }
01819 }
01820 
01821 static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
01822 {
01823     uint8_t downlinkDatarate = Datarates[datarate];
01824     RadioModems_t modem;
01825 
01826     if( Radio.GetStatus( ) == RF_IDLE )
01827     {
01828         Radio.SetChannel( freq );
01829 
01830         // Store downlink datarate
01831         McpsIndication.RxDatarate  = ( uint8_t ) datarate;
01832 
01833 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
01834         if( datarate == DR_7 )
01835         {
01836             modem = MODEM_FSK;
01837             Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, rxContinuous );
01838         }
01839         else
01840         {
01841             modem = MODEM_LORA;
01842             Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
01843         }
01844 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
01845         modem = MODEM_LORA;
01846         Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
01847 #endif
01848 
01849         if( RepeaterSupport == true )
01850         {
01851             Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRepeater[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
01852         }
01853         else
01854         {
01855             Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
01856         }
01857 
01858         if( rxContinuous == false )
01859         {
01860             Radio.Rx( MaxRxWindow );
01861         }
01862         else
01863         {
01864             Radio.Rx( 0 ); // Continuous mode
01865         }
01866     }
01867 }
01868 
01869 static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
01870 {
01871     uint16_t maxN = 0;
01872     uint16_t payloadSize = 0;
01873 
01874     // Get the maximum payload length
01875     if( RepeaterSupport == true )
01876     {
01877         maxN = MaxPayloadOfDatarateRepeater[datarate];
01878     }
01879     else
01880     {
01881         maxN = MaxPayloadOfDatarate[datarate];
01882     }
01883 
01884     // Calculate the resulting payload size
01885     payloadSize = ( lenN + fOptsLen );
01886 
01887     // Validation of the application payload size
01888     if( ( payloadSize <= maxN ) && ( payloadSize <= LORAMAC_PHY_MAXPAYLOAD ) )
01889     {
01890         return true;
01891     }
01892     return false;
01893 }
01894 
01895 static uint8_t CountBits( uint16_t mask, uint8_t nbBits )
01896 {
01897     uint8_t nbActiveBits = 0;
01898 
01899     for( uint8_t j = 0; j < nbBits; j++ )
01900     {
01901         if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
01902         {
01903             nbActiveBits++;
01904         }
01905     }
01906     return nbActiveBits;
01907 }
01908 
01909 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
01910 static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask )
01911 {
01912     uint8_t nb125kHzChannels = 0;
01913 
01914     for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
01915     {
01916         nb125kHzChannels += CountBits( channelsMask[k], 16 );
01917     }
01918 
01919     return nb125kHzChannels;
01920 }
01921 
01922 #if defined( USE_BAND_915_HYBRID )
01923 static void ReenableChannels( uint16_t mask, uint16_t* channelMask )
01924 {
01925     uint16_t blockMask = mask;
01926 
01927     for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
01928     {
01929         channelMask[i] = 0;
01930         if( ( blockMask & ( 1 << j ) ) != 0 )
01931         {
01932             channelMask[i] |= 0x00FF;
01933         }
01934         if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
01935         {
01936             channelMask[i] |= 0xFF00;
01937         }
01938     }
01939     channelMask[4] = blockMask;
01940     channelMask[5] = 0x0000;
01941 }
01942 
01943 static bool ValidateChannelMask( uint16_t* channelMask )
01944 {
01945     bool chanMaskState = false;
01946     uint16_t block1 = 0;
01947     uint16_t block2 = 0;
01948     uint8_t index = 0;
01949 
01950     for( uint8_t i = 0; i < 4; i++ )
01951     {
01952         block1 = channelMask[i] & 0x00FF;
01953         block2 = channelMask[i] & 0xFF00;
01954 
01955         if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) )
01956         {
01957             channelMask[i] &= block1;
01958             channelMask[4] = 1 << ( i * 2 );
01959             chanMaskState = true;
01960             index = i;
01961         }
01962         else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) )
01963         {
01964             channelMask[i] &= block2;
01965             channelMask[4] = 1 << ( i * 2 + 1 );
01966             chanMaskState = true;
01967             index = i;
01968         }
01969     }
01970 
01971     // Do only change the channel mask, if we have found a valid block.
01972     if( chanMaskState == true )
01973     {
01974         for( uint8_t i = 0; i < 4; i++ )
01975         {
01976             if( i != index )
01977             {
01978                 channelMask[i] = 0;
01979             }
01980         }
01981     }
01982     return chanMaskState;
01983 }
01984 #endif
01985 #endif
01986 
01987 static int8_t LimitTxPower( int8_t txPower )
01988 {
01989     int8_t resultTxPower = txPower;
01990 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
01991     if( ( ChannelsDatarate == DR_4 ) ||
01992         ( ( ChannelsDatarate >= DR_8 ) && ( ChannelsDatarate <= DR_13 ) ) )
01993     {// Limit tx power to max 26dBm
01994         resultTxPower =  MAX( txPower, TX_POWER_26_DBM );
01995     }
01996     else
01997     {
01998         if( CountNbEnabled125kHzChannels( ChannelsMask ) < 50 )
01999         {// Limit tx power to max 21dBm
02000             resultTxPower = MAX( txPower, TX_POWER_20_DBM );
02001         }
02002     }
02003 #endif
02004     return resultTxPower;
02005 }
02006 
02007 static bool ValueInRange( int8_t value, int8_t min, int8_t max )
02008 {
02009     if( ( value >= min ) && ( value <= max ) )
02010     {
02011         return true;
02012     }
02013     return false;
02014 }
02015 
02016 static bool DisableChannelInMask( uint8_t id, uint16_t* mask )
02017 {
02018     uint8_t index = 0;
02019     index = id / 16;
02020 
02021     if( ( index > 4 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
02022     {
02023         return false;
02024     }
02025 
02026     // Deactivate channel
02027     mask[index] &= ~( 1 << ( id % 16 ) );
02028 
02029     return true;
02030 }
02031 
02032 static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut )
02033 {
02034     bool adrAckReq = false;
02035     int8_t datarate = ChannelsDatarate;
02036 
02037     if( adrEnabled == true )
02038     {
02039         if( datarate == LORAMAC_TX_MIN_DATARATE )
02040         {
02041             AdrAckCounter = 0;
02042             adrAckReq = false;
02043         }
02044         else
02045         {
02046             if( AdrAckCounter >= ADR_ACK_LIMIT )
02047             {
02048                 adrAckReq = true;
02049             }
02050             else
02051             {
02052                 adrAckReq = false;
02053             }
02054             if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
02055             {
02056                 if( ( ( AdrAckCounter - ADR_ACK_DELAY ) % ADR_ACK_LIMIT ) == 0 )
02057                 {
02058 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
02059                     if( datarate > LORAMAC_TX_MIN_DATARATE )
02060                     {
02061                         datarate--;
02062                     }
02063                     if( datarate == LORAMAC_TX_MIN_DATARATE )
02064                     {
02065                         if( updateChannelMask == true )
02066                         {
02067 
02068                             // Re-enable default channels LC1, LC2, LC3
02069                             ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
02070                         }
02071                     }
02072 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
02073                     if( ( datarate > LORAMAC_TX_MIN_DATARATE ) && ( datarate == DR_8 ) )
02074                     {
02075                         datarate = DR_4;
02076                     }
02077                     else if( datarate > LORAMAC_TX_MIN_DATARATE )
02078                     {
02079                         datarate--;
02080                     }
02081                     if( datarate == LORAMAC_TX_MIN_DATARATE )
02082                     {
02083                         if( updateChannelMask == true )
02084                         {
02085 #if defined( USE_BAND_915 )
02086                             // Re-enable default channels
02087                             ChannelsMask[0] = 0xFFFF;
02088                             ChannelsMask[1] = 0xFFFF;
02089                             ChannelsMask[2] = 0xFFFF;
02090                             ChannelsMask[3] = 0xFFFF;
02091                             ChannelsMask[4] = 0x00FF;
02092                             ChannelsMask[5] = 0x0000;
02093 #else // defined( USE_BAND_915_HYBRID )
02094                             // Re-enable default channels
02095                             ReenableChannels( ChannelsMask[4], ChannelsMask );
02096 #endif
02097                         }
02098                     }
02099 #else
02100 #error "Please define a frequency band in the compiler options."
02101 #endif
02102                 }
02103             }
02104         }
02105     }
02106 
02107     *datarateOut = datarate;
02108 
02109     return adrAckReq;
02110 }
02111 
02112 static LoRaMacStatus_t  AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
02113 {
02114     LoRaMacStatus_t  status = LORAMAC_STATUS_BUSY ;
02115 
02116     switch( cmd )
02117     {
02118         case MOTE_MAC_LINK_CHECK_REQ :
02119             if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
02120             {
02121                 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
02122                 // No payload for this command
02123                 status = LORAMAC_STATUS_OK ;
02124             }
02125             break;
02126         case MOTE_MAC_LINK_ADR_ANS :
02127             if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
02128             {
02129                 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
02130                 // Margin
02131                 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
02132                 status = LORAMAC_STATUS_OK ;
02133             }
02134             break;
02135         case MOTE_MAC_DUTY_CYCLE_ANS :
02136             if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
02137             {
02138                 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
02139                 // No payload for this answer
02140                 status = LORAMAC_STATUS_OK ;
02141             }
02142             break;
02143         case MOTE_MAC_RX_PARAM_SETUP_ANS :
02144             if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
02145             {
02146                 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
02147                 // Status: Datarate ACK, Channel ACK
02148                 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
02149                 status = LORAMAC_STATUS_OK ;
02150             }
02151             break;
02152         case MOTE_MAC_DEV_STATUS_ANS :
02153             if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 2 ) )
02154             {
02155                 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
02156                 // 1st byte Battery
02157                 // 2nd byte Margin
02158                 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
02159                 MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
02160                 status = LORAMAC_STATUS_OK ;
02161             }
02162             break;
02163         case MOTE_MAC_NEW_CHANNEL_ANS :
02164             if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
02165             {
02166                 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
02167                 // Status: Datarate range OK, Channel frequency OK
02168                 MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
02169                 status = LORAMAC_STATUS_OK ;
02170             }
02171             break;
02172         case MOTE_MAC_RX_TIMING_SETUP_ANS :
02173             if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
02174             {
02175                 MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
02176                 // No payload for this answer
02177                 status = LORAMAC_STATUS_OK ;
02178             }
02179             break;
02180         default:
02181             return LORAMAC_STATUS_SERVICE_UNKNOWN ;
02182     }
02183     if( status == LORAMAC_STATUS_OK  )
02184     {
02185         MacCommandsInNextTx = true;
02186     }
02187     return status;
02188 }
02189 
02190 static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
02191 {
02192     while( macIndex < commandsSize )
02193     {
02194         // Decode Frame MAC commands
02195         switch( payload[macIndex++] )
02196         {
02197             case SRV_MAC_LINK_CHECK_ANS :
02198                 MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_OK ;
02199                 MlmeConfirm.DemodMargin  = payload[macIndex++];
02200                 MlmeConfirm.NbGateways  = payload[macIndex++];
02201                 break;
02202             case SRV_MAC_LINK_ADR_REQ :
02203                 {
02204                     uint8_t i;
02205                     uint8_t status = 0x07;
02206                     uint16_t chMask;
02207                     int8_t txPower = 0;
02208                     int8_t datarate = 0;
02209                     uint8_t nbRep = 0;
02210                     uint8_t chMaskCntl = 0;
02211                     uint16_t channelsMask[6] = { 0, 0, 0, 0, 0, 0 };
02212 
02213                     // Initialize local copy of the channels mask array
02214                     for( i = 0; i < 6; i++ )
02215                     {
02216                         channelsMask[i] = ChannelsMask[i];
02217                     }
02218                     datarate = payload[macIndex++];
02219                     txPower = datarate & 0x0F;
02220                     datarate = ( datarate >> 4 ) & 0x0F;
02221 
02222                     if( ( AdrCtrlOn == false ) &&
02223                         ( ( ChannelsDatarate != datarate ) || ( ChannelsTxPower != txPower ) ) )
02224                     { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower
02225                         // Answer the server with fail status
02226                         // Power ACK     = 0
02227                         // Data rate ACK = 0
02228                         // Channel mask  = 0
02229                         AddMacCommand( MOTE_MAC_LINK_ADR_ANS , 0, 0 );
02230                         macIndex += 3;  // Skip over the remaining bytes of the request
02231                         break;
02232                     }
02233                     chMask = ( uint16_t )payload[macIndex++];
02234                     chMask |= ( uint16_t )payload[macIndex++] << 8;
02235 
02236                     nbRep = payload[macIndex++];
02237                     chMaskCntl = ( nbRep >> 4 ) & 0x07;
02238                     nbRep &= 0x0F;
02239                     if( nbRep == 0 )
02240                     {
02241                         nbRep = 1;
02242                     }
02243 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
02244                     if( ( chMaskCntl == 0 ) && ( chMask == 0 ) )
02245                     {
02246                         status &= 0xFE; // Channel mask KO
02247                     }
02248                     else if( ( ( chMaskCntl >= 1 ) && ( chMaskCntl <= 5 )) ||
02249                              ( chMaskCntl >= 7 ) )
02250                     {
02251                         // RFU
02252                         status &= 0xFE; // Channel mask KO
02253                     }
02254                     else
02255                     {
02256                         for( i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
02257                         {
02258                             if( chMaskCntl == 6 )
02259                             {
02260                                 if( Channels[i].Frequency != 0 )
02261                                 {
02262                                     chMask |= 1 << i;
02263                                 }
02264                             }
02265                             else
02266                             {
02267                                 if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
02268                                     ( Channels[i].Frequency  == 0 ) )
02269                                 {// Trying to enable an undefined channel
02270                                     status &= 0xFE; // Channel mask KO
02271                                 }
02272                             }
02273                         }
02274                         channelsMask[0] = chMask;
02275                     }
02276 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
02277                     if( chMaskCntl == 6 )
02278                     {
02279                         // Enable all 125 kHz channels
02280                         for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
02281                         {
02282                             for( uint8_t j = 0; j < 16; j++ )
02283                             {
02284                                 if( Channels[i + j].Frequency != 0 )
02285                                 {
02286                                     channelsMask[k] |= 1 << j;
02287                                 }
02288                             }
02289                         }
02290                     }
02291                     else if( chMaskCntl == 7 )
02292                     {
02293                         // Disable all 125 kHz channels
02294                         channelsMask[0] = 0x0000;
02295                         channelsMask[1] = 0x0000;
02296                         channelsMask[2] = 0x0000;
02297                         channelsMask[3] = 0x0000;
02298                     }
02299                     else if( chMaskCntl == 5 )
02300                     {
02301                         // RFU
02302                         status &= 0xFE; // Channel mask KO
02303                     }
02304                     else
02305                     {
02306                         for( uint8_t i = 0; i < 16; i++ )
02307                         {
02308                             if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
02309                                 ( Channels[chMaskCntl * 16 + i].Frequency  == 0 ) )
02310                             {// Trying to enable an undefined channel
02311                                 status &= 0xFE; // Channel mask KO
02312                             }
02313                         }
02314                         channelsMask[chMaskCntl] = chMask;
02315 
02316                         if( CountNbEnabled125kHzChannels( channelsMask ) < 6 )
02317                         {
02318                             status &= 0xFE; // Channel mask KO
02319                         }
02320 
02321 #if defined( USE_BAND_915_HYBRID )
02322                         if( ValidateChannelMask( channelsMask ) == false )
02323                         {
02324                             status &= 0xFE; // Channel mask KO
02325                         }
02326 #endif
02327                     }
02328 #else
02329     #error "Please define a frequency band in the compiler options."
02330 #endif
02331                     if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
02332                     {
02333                         status &= 0xFD; // Datarate KO
02334                     }
02335 
02336                     //
02337                     // Remark MaxTxPower = 0 and MinTxPower = 5
02338                     //
02339                     if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) == false )
02340                     {
02341                         status &= 0xFB; // TxPower KO
02342                     }
02343                     if( ( status & 0x07 ) == 0x07 )
02344                     {
02345                         ChannelsDatarate = datarate;
02346                         ChannelsTxPower = txPower;
02347 
02348                         ChannelsMask[0] = channelsMask[0];
02349                         ChannelsMask[1] = channelsMask[1];
02350                         ChannelsMask[2] = channelsMask[2];
02351                         ChannelsMask[3] = channelsMask[3];
02352                         ChannelsMask[4] = channelsMask[4];
02353                         ChannelsMask[5] = channelsMask[5];
02354 
02355                         ChannelsNbRep = nbRep;
02356                     }
02357                     AddMacCommand( MOTE_MAC_LINK_ADR_ANS , status, 0 );
02358                 }
02359                 break;
02360             case SRV_MAC_DUTY_CYCLE_REQ :
02361                 MaxDCycle = payload[macIndex++];
02362                 AggregatedDCycle = 1 << MaxDCycle;
02363                 AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS , 0, 0 );
02364                 break;
02365             case SRV_MAC_RX_PARAM_SETUP_REQ :
02366                 {
02367                     uint8_t status = 0x07;
02368                     int8_t datarate = 0;
02369                     int8_t drOffset = 0;
02370                     uint32_t freq = 0;
02371 
02372                     drOffset = ( payload[macIndex] >> 4 ) & 0x07;
02373                     datarate = payload[macIndex] & 0x0F;
02374                     macIndex++;
02375 
02376                     freq =  ( uint32_t )payload[macIndex++];
02377                     freq |= ( uint32_t )payload[macIndex++] << 8;
02378                     freq |= ( uint32_t )payload[macIndex++] << 16;
02379                     freq *= 100;
02380 
02381                     if( Radio.CheckRfFrequency( freq ) == false )
02382                     {
02383                         status &= 0xFE; // Channel frequency KO
02384                     }
02385 
02386                     if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false )
02387                     {
02388                         status &= 0xFD; // Datarate KO
02389                     }
02390 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
02391                     if( ( ValueInRange( datarate, DR_5, DR_7 ) == true ) ||
02392                         ( datarate > DR_13 ) )
02393                     {
02394                         status &= 0xFD; // Datarate KO
02395                     }
02396 #endif
02397                     if( ValueInRange( drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET ) == false )
02398                     {
02399                         status &= 0xFB; // Rx1DrOffset range KO
02400                     }
02401 
02402                     if( ( status & 0x07 ) == 0x07 )
02403                     {
02404                         Rx2Channel.Datarate  = datarate;
02405                         Rx2Channel.Frequency  = freq;
02406                         Rx1DrOffset = drOffset;
02407                     }
02408                     AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS , status, 0 );
02409                 }
02410                 break;
02411             case SRV_MAC_DEV_STATUS_REQ :
02412                 {
02413                     uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE ;
02414                     if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) )
02415                     {
02416                         batteryLevel = LoRaMacCallbacks->GetBatteryLevel( );
02417                     }
02418                     AddMacCommand( MOTE_MAC_DEV_STATUS_ANS , batteryLevel, snr );
02419                     break;
02420                 }
02421             case SRV_MAC_NEW_CHANNEL_REQ :
02422                 {
02423                     uint8_t status = 0x03;
02424 
02425 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
02426                     status &= 0xFC; // Channel frequency and datarate KO
02427                     macIndex += 5;
02428 #else
02429                     int8_t channelIndex = 0;
02430                     ChannelParams_t  chParam;
02431 
02432                     channelIndex = payload[macIndex++];
02433                     chParam.Frequency  = ( uint32_t )payload[macIndex++];
02434                     chParam.Frequency  |= ( uint32_t )payload[macIndex++] << 8;
02435                     chParam.Frequency  |= ( uint32_t )payload[macIndex++] << 16;
02436                     chParam.Frequency  *= 100;
02437                     chParam.DrRange .Value  = payload[macIndex++];
02438 
02439                     LoRaMacState |= MAC_TX_CONFIG;
02440                     if( chParam.Frequency  == 0 )
02441                     {
02442                         if( channelIndex < 3 )
02443                         {
02444                             status &= 0xFC;
02445                         }
02446                         else
02447                         {
02448                             if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK  )
02449                             {
02450                                 status &= 0xFC;
02451                             }
02452                         }
02453                     }
02454                     else
02455                     {
02456                         switch( LoRaMacChannelAdd( channelIndex, chParam ) )
02457                         {
02458                             case LORAMAC_STATUS_OK :
02459                             {
02460                                 break;
02461                             }
02462                             case LORAMAC_STATUS_FREQUENCY_INVALID :
02463                             {
02464                                 status &= 0xFE;
02465                                 break;
02466                             }
02467                             case LORAMAC_STATUS_DATARATE_INVALID :
02468                             {
02469                                 status &= 0xFD;
02470                                 break;
02471                             }
02472                             case LORAMAC_STATUS_FREQ_AND_DR_INVALID :
02473                             {
02474                                 status &= 0xFC;
02475                                 break;
02476                             }
02477                             default:
02478                             {
02479                                 status &= 0xFC;
02480                                 break;
02481                             }
02482                         }
02483                     }
02484                     LoRaMacState &= ~MAC_TX_CONFIG;
02485 #endif
02486                     AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS , status, 0 );
02487                 }
02488                 break;
02489             case SRV_MAC_RX_TIMING_SETUP_REQ :
02490                 {
02491                     uint8_t delay = payload[macIndex++] & 0x0F;
02492 
02493                     if( delay == 0 )
02494                     {
02495                         delay++;
02496                     }
02497                     ReceiveDelay1 = delay * 1e6;
02498                     ReceiveDelay2 = ReceiveDelay1 + 1e6;
02499                     AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS , 0, 0 );
02500                 }
02501                 break;
02502             default:
02503                 // Unknown command. ABORT MAC commands processing
02504                 return;
02505         }
02506     }
02507 }
02508 
02509 LoRaMacStatus_t  Send( LoRaMacHeader_t  *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
02510 {
02511     LoRaMacFrameCtrl_t  fCtrl;
02512     LoRaMacStatus_t  status = LORAMAC_STATUS_PARAMETER_INVALID ;
02513 
02514     fCtrl.Value  = 0;
02515     fCtrl.Bits.FOptsLen       = 0;
02516     fCtrl.Bits.FPending       = 0;
02517     fCtrl.Bits.Ack            = false;
02518     fCtrl.Bits.AdrAckReq      = false;
02519     fCtrl.Bits.Adr            = AdrCtrlOn;
02520 
02521     // Prepare the frame
02522     status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize );
02523 
02524     // Validate status
02525     if( status != LORAMAC_STATUS_OK  )
02526     {
02527         return status;
02528     }
02529 
02530     // Reset confirm parameters
02531     McpsConfirm.NbRetries = 0;
02532     McpsConfirm.AckReceived = false;
02533     McpsConfirm.UpLinkCounter = UpLinkCounter;
02534 
02535     status = ScheduleTx( );
02536 
02537     return status;
02538 }
02539 
02540 static LoRaMacStatus_t  ScheduleTx( )
02541 {
02542     TimerTime_t dutyCycleTimeOff = 0;
02543 
02544     // Check if the device is off
02545     if( MaxDCycle == 255 )
02546     {
02547         return LORAMAC_STATUS_DEVICE_OFF ;
02548     }
02549     if( MaxDCycle == 0 )
02550     {
02551         AggregatedTimeOff = 0;
02552     }
02553 
02554     CalculateBackOff( LastTxChannel );
02555 
02556     // Select channel
02557     while( SetNextChannel( &dutyCycleTimeOff ) == false )
02558     {
02559         // Set the default datarate
02560         ChannelsDatarate = ChannelsDefaultDatarate;
02561 
02562 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
02563         // Re-enable default channels LC1, LC2, LC3
02564         ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
02565 #endif
02566     }
02567 
02568     // Schedule transmission of frame
02569     if( dutyCycleTimeOff == 0 )
02570     {
02571         // Try to send now
02572         return SendFrameOnChannel( Channels[Channel] );
02573     }
02574     else
02575     {
02576         // Send later - prepare timer
02577         LoRaMacState |= MAC_TX_DELAYED;
02578         TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
02579         TimerStart( &TxDelayedTimer );
02580 
02581         return LORAMAC_STATUS_OK ;
02582     }
02583 }
02584 
02585 static void CalculateBackOff( uint8_t channel )
02586 {
02587     uint16_t dutyCycle = Bands[Channels[channel].Band ].DCycle ;
02588 
02589     if( IsLoRaMacNetworkJoined == false )
02590     {
02591 #if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
02592         dutyCycle = JOIN_DC;
02593 #endif
02594     }
02595 
02596     // Update Band Time OFF
02597     if( DutyCycleOn == true )
02598     {
02599         Bands[Channels[channel].Band ].TimeOff  = TxTimeOnAir * dutyCycle - TxTimeOnAir;
02600     }
02601     else
02602     {
02603         Bands[Channels[channel].Band ].TimeOff  = 0;
02604     }
02605     // Update Aggregated Time OFF
02606     AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
02607 }
02608 
02609 LoRaMacStatus_t  PrepareFrame( LoRaMacHeader_t  *macHdr, LoRaMacFrameCtrl_t  *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
02610 {
02611     uint16_t i;
02612     uint8_t pktHeaderLen = 0;
02613     uint32_t mic = 0;
02614     const void* payload = fBuffer;
02615     uint8_t payloadSize = fBufferSize;
02616     uint8_t framePort = fPort;
02617 
02618     LoRaMacBufferPktLen = 0;
02619 
02620     NodeAckRequested = false;
02621 
02622     if( fBuffer == NULL )
02623     {
02624         fBufferSize = 0;
02625     }
02626 
02627     LoRaMacBuffer[pktHeaderLen++] = macHdr->Value ;
02628 
02629     switch( macHdr->Bits.MType  )
02630     {
02631         case FRAME_TYPE_JOIN_REQ :
02632             RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
02633             RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
02634 
02635             LoRaMacBufferPktLen = pktHeaderLen;
02636 
02637             memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
02638             LoRaMacBufferPktLen += 8;
02639             memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8 );
02640             LoRaMacBufferPktLen += 8;
02641 
02642             LoRaMacDevNonce = Radio.Random( );
02643 
02644             LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
02645             LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF;
02646 
02647             LoRaMacJoinComputeMic ( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic );
02648 
02649             LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
02650             LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
02651             LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
02652             LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
02653 
02654             break;
02655         case FRAME_TYPE_DATA_CONFIRMED_UP :
02656             NodeAckRequested = true;
02657             //Intentional falltrough
02658         case FRAME_TYPE_DATA_UNCONFIRMED_UP :
02659             if( IsLoRaMacNetworkJoined == false )
02660             {
02661                 return LORAMAC_STATUS_NO_NETWORK_JOINED ; // No network has been joined yet
02662             }
02663 
02664             fCtrl->Bits.AdrAckReq  = AdrNextDr( fCtrl->Bits.Adr , true, &ChannelsDatarate );
02665 
02666             if( ValidatePayloadLength( fBufferSize, ChannelsDatarate, MacCommandsBufferIndex ) == false )
02667             {
02668                 return LORAMAC_STATUS_LENGTH_ERROR ;
02669             }
02670 
02671             RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME;
02672             RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME;
02673 
02674             if( SrvAckRequested == true )
02675             {
02676                 SrvAckRequested = false;
02677                 fCtrl->Bits.Ack  = 1;
02678             }
02679 
02680             LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
02681             LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
02682             LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
02683             LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;
02684 
02685             LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value ;
02686 
02687             LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
02688             LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
02689 
02690             if( ( payload != NULL ) && ( payloadSize > 0 ) )
02691             {
02692                 if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
02693                 {
02694                     fCtrl->Bits.FOptsLen  += MacCommandsBufferIndex;
02695 
02696                     // Update FCtrl field with new value of OptionsLength
02697                     LoRaMacBuffer[0x05] = fCtrl->Value ;
02698                     for( i = 0; i < MacCommandsBufferIndex; i++ )
02699                     {
02700                         LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
02701                     }
02702                 }
02703             }
02704             else
02705             {
02706                 if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
02707                 {
02708                     payloadSize = MacCommandsBufferIndex;
02709                     payload = MacCommandsBuffer;
02710                     framePort = 0;
02711                 }
02712             }
02713             MacCommandsInNextTx = false;
02714             MacCommandsBufferIndex = 0;
02715 
02716             if( ( payload != NULL ) && ( payloadSize > 0 ) )
02717             {
02718                 LoRaMacBuffer[pktHeaderLen++] = framePort;
02719 
02720                 if( framePort == 0 )
02721                 {
02722                     LoRaMacPayloadEncrypt ( (uint8_t* ) payload, payloadSize, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
02723                 }
02724                 else
02725                 {
02726                     LoRaMacPayloadEncrypt ( (uint8_t* ) payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
02727                 }
02728                 memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize );
02729             }
02730             LoRaMacBufferPktLen = pktHeaderLen + payloadSize;
02731 
02732             LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
02733 
02734             LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
02735             LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF;
02736             LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF;
02737             LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
02738 
02739             LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
02740 
02741             break;
02742         case FRAME_TYPE_PROPRIETARY :
02743             if( ( fBuffer != NULL ) && ( fBufferSize > 0 ) )
02744             {
02745                 memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, fBufferSize );
02746                 LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
02747             }
02748             break;
02749         default:
02750             return LORAMAC_STATUS_SERVICE_UNKNOWN ;
02751     }
02752 
02753     return LORAMAC_STATUS_OK ;
02754 }
02755 
02756 LoRaMacStatus_t  SendFrameOnChannel( ChannelParams_t  channel )
02757 {
02758     int8_t datarate = Datarates[ChannelsDatarate];
02759     int8_t txPowerIndex = 0;
02760     int8_t txPower = 0;
02761 
02762     txPowerIndex = LimitTxPower( ChannelsTxPower );
02763     txPower = TxPowers[txPowerIndex];
02764 
02765     MlmeConfirm.Status  = LORAMAC_EVENT_INFO_STATUS_ERROR ;
02766     McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
02767     McpsConfirm.Datarate = ChannelsDatarate;
02768     McpsConfirm.TxPower = txPowerIndex;
02769 
02770     Radio.SetChannel( channel.Frequency  );
02771 
02772 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
02773     if( ChannelsDatarate == DR_7 )
02774     { // High Speed FSK channel
02775         Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
02776         Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
02777         TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
02778 
02779     }
02780     else if( ChannelsDatarate == DR_6 )
02781     { // High speed LoRa channel
02782         Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
02783         Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
02784         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
02785     }
02786     else
02787     { // Normal LoRa channel
02788         Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
02789         Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
02790         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
02791     }
02792 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
02793     Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
02794     if( ChannelsDatarate >= DR_4 )
02795     { // High speed LoRa channel BW500 kHz
02796         Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
02797         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
02798     }
02799     else
02800     { // Normal LoRa channel
02801         Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
02802         TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
02803     }
02804 #else
02805     #error "Please define a frequency band in the compiler options."
02806 #endif
02807 
02808     // Store the time on air
02809     McpsConfirm.TxTimeOnAir = TxTimeOnAir;
02810     MlmeConfirm.TxTimeOnAir  = TxTimeOnAir;
02811 
02812     // Starts the MAC layer status check timer
02813     TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
02814     TimerStart( &MacStateCheckTimer );
02815 
02816     // Send now
02817     Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
02818 
02819     LoRaMacState |= MAC_TX_RUNNING;
02820 
02821     return LORAMAC_STATUS_OK ;
02822 }
02823 
02824 LoRaMacStatus_t  LoRaMacInitialization( LoRaMacPrimitives_t  *primitives, LoRaMacCallback_t *callbacks )
02825 {
02826     if( primitives == NULL )
02827     {
02828         return LORAMAC_STATUS_PARAMETER_INVALID ;
02829     }
02830 
02831     if( ( primitives->MacMcpsConfirm == NULL ) ||
02832         ( primitives->MacMcpsIndication == NULL ) ||
02833         ( primitives->MacMlmeConfirm == NULL ))
02834     {
02835         return LORAMAC_STATUS_PARAMETER_INVALID ;
02836     }
02837 
02838     LoRaMacPrimitives = primitives;
02839     LoRaMacCallbacks = callbacks;
02840 
02841     LoRaMacFlags.Value  = 0;
02842 
02843     LoRaMacDeviceClass = CLASS_A ;
02844 
02845     UpLinkCounter = 1;
02846     DownLinkCounter = 0;
02847     AdrAckCounter = 0;
02848 
02849     RepeaterSupport = false;
02850     IsRxWindowsEnabled = true;
02851     IsLoRaMacNetworkJoined = false;
02852     LoRaMacState = MAC_IDLE;
02853 
02854 #if defined( USE_BAND_433 )
02855     ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
02856 #elif defined( USE_BAND_780 )
02857     ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
02858 #elif defined( USE_BAND_868 )
02859     ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
02860 #elif defined( USE_BAND_915 )
02861     ChannelsMask[0] = 0xFFFF;
02862     ChannelsMask[1] = 0xFFFF;
02863     ChannelsMask[2] = 0xFFFF;
02864     ChannelsMask[3] = 0xFFFF;
02865     ChannelsMask[4] = 0x00FF;
02866     ChannelsMask[5] = 0x0000;
02867 
02868     memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );
02869 #elif defined( USE_BAND_915_HYBRID )
02870     ChannelsMask[0] = 0x00FF;
02871     ChannelsMask[1] = 0x0000;
02872     ChannelsMask[2] = 0x0000;
02873     ChannelsMask[3] = 0x0000;
02874     ChannelsMask[4] = 0x0001;
02875     ChannelsMask[5] = 0x0000;
02876     
02877     memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );   //save channel mask in memory
02878 #else
02879     #error "Please define a frequency band in the compiler options."
02880 #endif
02881 
02882 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )   //set frequency for channels
02883     // 125 kHz channels
02884     for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ )
02885     {
02886         Channels[i].Frequency  = 902.3e6 + i * 200e3;
02887         Channels[i].DrRange .Value  = ( DR_3 << 4 ) | DR_0;
02888         Channels[i].Band  = 0;
02889     }
02890     // 500 kHz channels1
02891     for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ )
02892     {
02893         Channels[i].Frequency  = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6;
02894         Channels[i].DrRange .Value  = ( DR_4 << 4 ) | DR_4;
02895         Channels[i].Band  = 0;
02896     }
02897 #endif
02898 
02899     ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
02900     ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
02901     ChannelsNbRep = 1;
02902     ChannelsNbRepCounter = 0;
02903 
02904     MaxDCycle = 0;
02905     AggregatedDCycle = 1;
02906     AggregatedLastTxDoneTime = 0;
02907     AggregatedTimeOff = 0;
02908 
02909 #if defined( USE_BAND_433 )
02910     DutyCycleOn = false;
02911 #elif defined( USE_BAND_780 )
02912     DutyCycleOn = false;
02913 #elif defined( USE_BAND_868 )
02914     DutyCycleOn = true;
02915 #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
02916     DutyCycleOn = false;
02917 #else
02918     #error "Please define a frequency band in the compiler options."
02919 #endif
02920 
02921     MaxRxWindow = MAX_RX_WINDOW;
02922     ReceiveDelay1 = RECEIVE_DELAY1;
02923     ReceiveDelay2 = RECEIVE_DELAY2;
02924     JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
02925     JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
02926 
02927     TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
02928     TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
02929 
02930     TimerInit( &TxDelayedTimer, OnTxDelayedTimerEvent );
02931     TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent );
02932     TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
02933     TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
02934 
02935     // Initialize Radio driver
02936     RadioEvents.TxDone = OnRadioTxDone;
02937     RadioEvents.RxDone = OnRadioRxDone;
02938     RadioEvents.RxError = OnRadioRxError;
02939     RadioEvents.TxTimeout = OnRadioTxTimeout;
02940     RadioEvents.RxTimeout = OnRadioRxTimeout;
02941     Radio.Init( &RadioEvents );
02942 
02943     // Random seed initialization
02944     srand1( Radio.Random( ) );
02945 
02946     // Initialize channel index.
02947     Channel = LORA_MAX_NB_CHANNELS;
02948 
02949     PublicNetwork = true;
02950     SetPublicNetwork( PublicNetwork );
02951     Radio.Sleep( );
02952 
02953     return LORAMAC_STATUS_OK ;
02954 }
02955 
02956 LoRaMacStatus_t  LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t * txInfo )
02957 {
02958     int8_t datarate = ChannelsDefaultDatarate;
02959 
02960     if( txInfo == NULL )
02961     {
02962         return LORAMAC_STATUS_PARAMETER_INVALID ;
02963     }
02964 
02965     AdrNextDr( AdrCtrlOn, false, &datarate );
02966 
02967     if( RepeaterSupport == true )
02968     {
02969         txInfo->CurrentPayloadSize  = MaxPayloadOfDatarateRepeater[datarate];
02970     }
02971     else
02972     {
02973         txInfo->CurrentPayloadSize  = MaxPayloadOfDatarate[datarate];
02974     }
02975 
02976     if( txInfo->CurrentPayloadSize  >= MacCommandsBufferIndex )
02977     {
02978         txInfo->MaxPossiblePayload  = txInfo->CurrentPayloadSize  - MacCommandsBufferIndex;
02979     }
02980     else
02981     {
02982         return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR ;
02983     }
02984 
02985     if( ValidatePayloadLength( size, datarate, 0 ) == false )
02986     {
02987         return LORAMAC_STATUS_LENGTH_ERROR ;
02988     }
02989 
02990     if( ValidatePayloadLength( size, datarate, MacCommandsBufferIndex ) == false )
02991     {
02992         return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR ;
02993     }
02994 
02995     return LORAMAC_STATUS_OK ;
02996 }
02997 
02998 LoRaMacStatus_t  LoRaMacMibGetRequestConfirm( MibRequestConfirm_t  *mibGet )
02999 {
03000     LoRaMacStatus_t  status = LORAMAC_STATUS_OK ;
03001 
03002     if( mibGet == NULL )
03003     {
03004         return LORAMAC_STATUS_PARAMETER_INVALID ;
03005     }
03006 
03007     switch( mibGet->Type  )
03008     {
03009         case MIB_DEVICE_CLASS :
03010         {
03011             mibGet->Param .Class  = LoRaMacDeviceClass;
03012             break;
03013         }
03014         case MIB_NETWORK_JOINED :
03015         {
03016             mibGet->Param .IsNetworkJoined  = IsLoRaMacNetworkJoined;
03017             break;
03018         }
03019         case MIB_ADR :
03020         {
03021             mibGet->Param .AdrEnable  = AdrCtrlOn;
03022             break;
03023         }
03024         case MIB_NET_ID :
03025         {
03026             mibGet->Param .NetID  = LoRaMacNetID;
03027             break;
03028         }
03029         case MIB_DEV_ADDR :
03030         {
03031             mibGet->Param .DevAddr  = LoRaMacDevAddr;
03032             break;
03033         }
03034         case MIB_NWK_SKEY :
03035         {
03036             mibGet->Param .NwkSKey  = LoRaMacNwkSKey;
03037             break;
03038         }
03039         case MIB_APP_SKEY :
03040         {
03041             mibGet->Param .AppSKey  = LoRaMacAppSKey;
03042             break;
03043         }
03044         case MIB_PUBLIC_NETWORK :
03045         {
03046             mibGet->Param .EnablePublicNetwork  = PublicNetwork;
03047             break;
03048         }
03049         case MIB_REPEATER_SUPPORT :
03050         {
03051             mibGet->Param .EnableRepeaterSupport  = RepeaterSupport;
03052             break;
03053         }
03054         case MIB_CHANNELS :
03055         {
03056             mibGet->Param .ChannelList  = Channels;
03057             break;
03058         }
03059         case MIB_RX2_CHANNEL :
03060         {
03061             mibGet->Param .Rx2Channel  = Rx2Channel;
03062             break;
03063         }
03064         case MIB_CHANNELS_MASK :
03065         {
03066             mibGet->Param .ChannelsMask  = ChannelsMask;
03067             break;
03068         }
03069         case MIB_CHANNELS_NB_REP :
03070         {
03071             mibGet->Param .ChannelNbRep  = ChannelsNbRep;
03072             break;
03073         }
03074         case MIB_MAX_RX_WINDOW_DURATION :
03075         {
03076             mibGet->Param .MaxRxWindow  = MaxRxWindow;
03077             break;
03078         }
03079         case MIB_RECEIVE_DELAY_1 :
03080         {
03081             mibGet->Param .ReceiveDelay1  = ReceiveDelay1;
03082             break;
03083         }
03084         case MIB_RECEIVE_DELAY_2 :
03085         {
03086             mibGet->Param .ReceiveDelay2  = ReceiveDelay2;
03087             break;
03088         }
03089         case MIB_JOIN_ACCEPT_DELAY_1 :
03090         {
03091             mibGet->Param .JoinAcceptDelay1  = JoinAcceptDelay1;
03092             break;
03093         }
03094         case MIB_JOIN_ACCEPT_DELAY_2 :
03095         {
03096             mibGet->Param .JoinAcceptDelay2  = JoinAcceptDelay2;
03097             break;
03098         }
03099         case MIB_CHANNELS_DEFAULT_DATARATE :
03100         {
03101             mibGet->Param .ChannelsDefaultDatarate  = ChannelsDefaultDatarate;
03102             break;
03103         }
03104         case MIB_CHANNELS_DATARATE :
03105         {
03106             mibGet->Param .ChannelsDatarate  = ChannelsDatarate;
03107             break;
03108         }
03109         case MIB_CHANNELS_TX_POWER :
03110         {
03111             mibGet->Param .ChannelsTxPower  = ChannelsTxPower;
03112             break;
03113         }
03114         case MIB_UPLINK_COUNTER :
03115         {
03116             mibGet->Param .UpLinkCounter  = UpLinkCounter;
03117             break;
03118         }
03119         case MIB_DOWNLINK_COUNTER :
03120         {
03121             mibGet->Param .DownLinkCounter  = DownLinkCounter;
03122             break;
03123         }
03124         case MIB_MULTICAST_CHANNEL :
03125         {
03126             mibGet->Param .MulticastList  = MulticastChannels;
03127             break;
03128         }
03129         default:
03130             status = LORAMAC_STATUS_SERVICE_UNKNOWN ;
03131             break;
03132     }
03133 
03134     return status;
03135 }
03136 
03137 LoRaMacStatus_t  LoRaMacMibSetRequestConfirm( MibRequestConfirm_t  *mibSet )
03138 {
03139     LoRaMacStatus_t  status = LORAMAC_STATUS_OK ;
03140 
03141     if( mibSet == NULL )
03142     {
03143         return LORAMAC_STATUS_PARAMETER_INVALID ;
03144     }
03145     if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
03146     {
03147         return LORAMAC_STATUS_BUSY ;
03148     }
03149 
03150     switch( mibSet->Type  )
03151     {
03152         case MIB_DEVICE_CLASS :
03153         {
03154             LoRaMacDeviceClass = mibSet->Param .Class ;
03155             switch( LoRaMacDeviceClass )
03156             {
03157                 case CLASS_A :
03158                 {
03159                     // Set the radio into sleep to setup a defined state
03160                     Radio.Sleep( );
03161                     break;
03162                 }
03163                 case CLASS_B :
03164                 {
03165                     break;
03166                 }
03167                 case CLASS_C :
03168                 {
03169                     // Set the NodeAckRequested indicator to default
03170                     NodeAckRequested = false;
03171                     OnRxWindow2TimerEvent( );
03172                     break;
03173                 }
03174             }
03175             break;
03176         }
03177         case MIB_NETWORK_JOINED :
03178         {
03179             IsLoRaMacNetworkJoined = mibSet->Param .IsNetworkJoined ;
03180             break;
03181         }
03182         case MIB_ADR :
03183         {
03184             AdrCtrlOn = mibSet->Param .AdrEnable ;
03185             break;
03186         }
03187         case MIB_NET_ID :
03188         {
03189             LoRaMacNetID = mibSet->Param .NetID ;
03190             break;
03191         }
03192         case MIB_DEV_ADDR :
03193         {
03194             LoRaMacDevAddr = mibSet->Param .DevAddr ;
03195             break;
03196         }
03197         case MIB_NWK_SKEY :
03198         {
03199             if( mibSet->Param .NwkSKey  != NULL )
03200             {
03201                 memcpy1( LoRaMacNwkSKey, mibSet->Param .NwkSKey ,
03202                                sizeof( LoRaMacNwkSKey ) );
03203             }
03204             else
03205             {
03206                 status = LORAMAC_STATUS_PARAMETER_INVALID ;
03207             }
03208             break;
03209         }
03210         case MIB_APP_SKEY :
03211         {
03212             if( mibSet->Param .AppSKey  != NULL )
03213             {
03214                 memcpy1( LoRaMacAppSKey, mibSet->Param .AppSKey ,
03215                                sizeof( LoRaMacAppSKey ) );
03216             }
03217             else
03218             {
03219                 status = LORAMAC_STATUS_PARAMETER_INVALID ;
03220             }
03221             break;
03222         }
03223         case MIB_PUBLIC_NETWORK :
03224         {
03225             SetPublicNetwork( mibSet->Param .EnablePublicNetwork  );
03226             break;
03227         }
03228         case MIB_REPEATER_SUPPORT :
03229         {
03230              RepeaterSupport = mibSet->Param .EnableRepeaterSupport ;
03231             break;
03232         }
03233         case MIB_RX2_CHANNEL :
03234         {
03235             Rx2Channel = mibSet->Param .Rx2Channel ;
03236             break;
03237         }
03238         case MIB_CHANNELS_MASK :
03239         {
03240             if( mibSet->Param .ChannelsMask  )
03241             {
03242 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
03243                 bool chanMaskState = true;
03244 
03245 #if defined( USE_BAND_915_HYBRID )
03246                 chanMaskState = ValidateChannelMask( mibSet->Param .ChannelsMask  );
03247 #endif
03248                 if( chanMaskState == true )
03249                 {
03250                     if( ( CountNbEnabled125kHzChannels( mibSet->Param .ChannelsMask  ) < 6 ) &&
03251                         ( CountNbEnabled125kHzChannels( mibSet->Param .ChannelsMask  ) > 0 ) )
03252                     {
03253                         status = LORAMAC_STATUS_PARAMETER_INVALID ;
03254                     }
03255                     else
03256                     {
03257                         memcpy1( ( uint8_t* ) ChannelsMask,
03258                                  ( uint8_t* ) mibSet->Param .ChannelsMask , sizeof( ChannelsMask ) );
03259                         for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ )
03260                         {
03261                             // Disable channels which are no longer available
03262                             ChannelsMaskRemaining[i] &= ChannelsMask[i];                            
03263                         }
03264                     }
03265                 }
03266                 else
03267                 {
03268                     status = LORAMAC_STATUS_PARAMETER_INVALID ;
03269                 }
03270 #else
03271                 memcpy1( ( uint8_t* ) ChannelsMask,
03272                          ( uint8_t* ) mibSet->Param .ChannelsMask , 2 );
03273 #endif
03274             }
03275             else
03276             {
03277                 status = LORAMAC_STATUS_PARAMETER_INVALID ;
03278             }
03279             break;
03280         }
03281         case MIB_CHANNELS_NB_REP :
03282         {
03283             if( ( mibSet->Param .ChannelNbRep  >= 1 ) &&
03284                 ( mibSet->Param .ChannelNbRep  <= 15 ) )
03285             {
03286                 ChannelsNbRep = mibSet->Param .ChannelNbRep ;
03287             }
03288             else
03289             {
03290                 status = LORAMAC_STATUS_PARAMETER_INVALID ;
03291             }
03292             break;
03293         }
03294         case MIB_MAX_RX_WINDOW_DURATION :
03295         {
03296             MaxRxWindow = mibSet->Param .MaxRxWindow ;
03297             break;
03298         }
03299         case MIB_RECEIVE_DELAY_1 :
03300         {
03301             ReceiveDelay1 = mibSet->Param .ReceiveDelay1 ;
03302             break;
03303         }
03304         case MIB_RECEIVE_DELAY_2 :
03305         {
03306             ReceiveDelay2 = mibSet->Param .ReceiveDelay2 ;
03307             break;
03308         }
03309         case MIB_JOIN_ACCEPT_DELAY_1 :
03310         {
03311             JoinAcceptDelay1 = mibSet->Param .JoinAcceptDelay1 ;
03312             break;
03313         }
03314         case MIB_JOIN_ACCEPT_DELAY_2 :
03315         {
03316             JoinAcceptDelay2 = mibSet->Param .JoinAcceptDelay2 ;
03317             break;
03318         }
03319         case MIB_CHANNELS_DEFAULT_DATARATE :
03320         {
03321             if( ValueInRange( mibSet->Param .ChannelsDefaultDatarate ,
03322                               LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
03323             {
03324                 ChannelsDefaultDatarate = mibSet->Param .ChannelsDefaultDatarate ;
03325             }
03326             else
03327             {
03328                 status = LORAMAC_STATUS_PARAMETER_INVALID ;
03329             }
03330             break;
03331         }
03332         case MIB_CHANNELS_DATARATE :
03333         {
03334             if( ValueInRange( mibSet->Param .ChannelsDatarate ,
03335                               LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
03336             {
03337                 ChannelsDatarate = mibSet->Param .ChannelsDatarate ;
03338             }
03339             else
03340             {
03341                 status = LORAMAC_STATUS_PARAMETER_INVALID ;
03342             }
03343             break;
03344         }
03345         case MIB_CHANNELS_TX_POWER :
03346         {
03347             if( ValueInRange( mibSet->Param .ChannelsTxPower ,
03348                               LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
03349             {
03350                 ChannelsTxPower = mibSet->Param .ChannelsTxPower ;
03351             }
03352             else
03353             {
03354                 status = LORAMAC_STATUS_PARAMETER_INVALID ;
03355             }
03356             break;
03357         }
03358         case MIB_UPLINK_COUNTER :
03359         {
03360             UpLinkCounter = mibSet->Param .UpLinkCounter ;
03361             break;
03362         }
03363         case MIB_DOWNLINK_COUNTER :
03364         {
03365             DownLinkCounter = mibSet->Param .DownLinkCounter ;
03366             break;
03367         }
03368         default:
03369             status = LORAMAC_STATUS_SERVICE_UNKNOWN ;
03370             break;
03371     }
03372 
03373     return status;
03374 }
03375 
03376 LoRaMacStatus_t  LoRaMacChannelAdd( uint8_t id, ChannelParams_t  params )
03377 {
03378 #if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
03379     return LORAMAC_STATUS_PARAMETER_INVALID ;
03380 #else
03381     bool datarateInvalid = false;
03382     bool frequencyInvalid = false;
03383     uint8_t band = 0;
03384 
03385     // The id must not exceed LORA_MAX_NB_CHANNELS
03386     if( id >= LORA_MAX_NB_CHANNELS )
03387     {
03388         return LORAMAC_STATUS_PARAMETER_INVALID ;
03389     }
03390     // Validate if the MAC is in a correct state
03391     if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
03392     {
03393         if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
03394         {
03395             return LORAMAC_STATUS_BUSY ;
03396         }
03397     }
03398     // Validate the datarate
03399     if( ( params.DrRange .Fields.Min  > params.DrRange .Fields.Max  ) ||
03400         ( ValueInRange( params.DrRange .Fields.Min , LORAMAC_TX_MIN_DATARATE,
03401                         LORAMAC_TX_MAX_DATARATE ) == false ) ||
03402         ( ValueInRange( params.DrRange .Fields.Max , LORAMAC_TX_MIN_DATARATE,
03403                         LORAMAC_TX_MAX_DATARATE ) == false ) )
03404     {
03405         datarateInvalid = true;
03406     }
03407 
03408 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
03409     if( id < 3 )
03410     {
03411         if( params.Frequency  != Channels[id].Frequency  )
03412         {
03413             frequencyInvalid = true;
03414         }
03415 
03416         if( params.DrRange .Fields.Min  > ChannelsDefaultDatarate )
03417         {
03418             datarateInvalid = true;
03419         }
03420         if( ValueInRange( params.DrRange .Fields.Max , DR_5, LORAMAC_TX_MAX_DATARATE ) == false )
03421         {
03422             datarateInvalid = true;
03423         }
03424     }
03425 #endif
03426 
03427     // Validate the frequency
03428     if( ( Radio.CheckRfFrequency( params.Frequency  ) == true ) && ( params.Frequency  > 0 ) && ( frequencyInvalid == false ) )
03429     {
03430 #if defined( USE_BAND_868 )
03431         if( ( params.Frequency  >= 865000000 ) && ( params.Frequency  <= 868000000 ) )
03432         {
03433             band = BAND_G1_0;
03434         }
03435         else if( ( params.Frequency  > 868000000 ) && ( params.Frequency  <= 868600000 ) )
03436         {
03437             band = BAND_G1_1;
03438         }
03439         else if( ( params.Frequency  >= 868700000 ) && ( params.Frequency  <= 869200000 ) )
03440         {
03441             band = BAND_G1_2;
03442         }
03443         else if( ( params.Frequency  >= 869400000 ) && ( params.Frequency  <= 869650000 ) )
03444         {
03445             band = BAND_G1_3;
03446         }
03447         else if( ( params.Frequency  >= 869700000 ) && ( params.Frequency  <= 870000000 ) )
03448         {
03449             band = BAND_G1_4;
03450         }
03451         else
03452         {
03453             frequencyInvalid = true;
03454         }
03455 #endif
03456     }
03457     else
03458     {
03459         frequencyInvalid = true;
03460     }
03461 
03462     if( ( datarateInvalid == true ) && ( frequencyInvalid == true ) )
03463     {
03464         return LORAMAC_STATUS_FREQ_AND_DR_INVALID ;
03465     }
03466     if( datarateInvalid == true )
03467     {
03468         return LORAMAC_STATUS_DATARATE_INVALID ;
03469     }
03470     if( frequencyInvalid == true )
03471     {
03472         return LORAMAC_STATUS_FREQUENCY_INVALID ;
03473     }
03474 
03475     // Every parameter is valid, activate the channel
03476     Channels[id] = params;
03477     Channels[id].Band  = band;
03478     ChannelsMask[0] |= ( 1 << id );
03479 
03480     return LORAMAC_STATUS_OK ;
03481 #endif
03482 }
03483 
03484 LoRaMacStatus_t  LoRaMacChannelRemove( uint8_t id )
03485 {
03486 #if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
03487     if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
03488     {
03489         if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
03490         {
03491             return LORAMAC_STATUS_BUSY ;
03492         }
03493     }
03494 
03495     if( ( id < 3 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
03496     {
03497         return LORAMAC_STATUS_PARAMETER_INVALID ;
03498     }
03499     else
03500     {
03501         // Remove the channel from the list of channels
03502         Channels[id] = ( ChannelParams_t  ){ 0, { 0 }, 0 };
03503 
03504         // Disable the channel as it doesn't exist anymore
03505         if( DisableChannelInMask( id, ChannelsMask ) == false )
03506         {
03507             return LORAMAC_STATUS_PARAMETER_INVALID ;
03508         }
03509     }
03510     return LORAMAC_STATUS_OK ;
03511 #elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
03512     return LORAMAC_STATUS_PARAMETER_INVALID ;
03513 #endif
03514 }
03515 
03516 LoRaMacStatus_t  LoRaMacMulticastChannelLink( MulticastParams_t  *channelParam )
03517 {
03518     if( channelParam == NULL )
03519     {
03520         return LORAMAC_STATUS_PARAMETER_INVALID ;
03521     }
03522     if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
03523     {
03524         return LORAMAC_STATUS_BUSY ;
03525     }
03526 
03527     // Reset downlink counter
03528     channelParam->DownLinkCounter  = 0;
03529 
03530     if( MulticastChannels == NULL )
03531     {
03532         // New node is the fist element
03533         MulticastChannels = channelParam;
03534     }
03535     else
03536     {
03537         MulticastParams_t  *cur = MulticastChannels;
03538 
03539         // Search the last node in the list
03540         while( cur->Next  != NULL )
03541         {
03542             cur = cur->Next ;
03543         }
03544         // This function always finds the last node
03545         cur->Next  = channelParam;
03546     }
03547 
03548     return LORAMAC_STATUS_OK ;
03549 }
03550 
03551 LoRaMacStatus_t  LoRaMacMulticastChannelUnlink( MulticastParams_t  *channelParam )
03552 {
03553     if( channelParam == NULL )
03554     {
03555         return LORAMAC_STATUS_PARAMETER_INVALID ;
03556     }
03557     if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
03558     {
03559         return LORAMAC_STATUS_BUSY ;
03560     }
03561 
03562     if( MulticastChannels != NULL )
03563     {
03564         if( MulticastChannels == channelParam )
03565         {
03566           // First element
03567           MulticastChannels = channelParam->Next ;
03568         }
03569         else
03570         {
03571             MulticastParams_t  *cur = MulticastChannels;
03572 
03573             // Search the node in the list
03574             while( cur->Next  && cur->Next  != channelParam )
03575             {
03576                 cur = cur->Next ;
03577             }
03578             // If we found the node, remove it
03579             if( cur->Next  )
03580             {
03581                 cur->Next  = channelParam->Next ;
03582             }
03583         }
03584         channelParam->Next  = NULL;
03585     }
03586 
03587     return LORAMAC_STATUS_OK ;
03588 }
03589 
03590 LoRaMacStatus_t  LoRaMacMlmeRequest( MlmeReq_t  *mlmeRequest )
03591 {
03592     LoRaMacStatus_t  status = LORAMAC_STATUS_SERVICE_UNKNOWN ;
03593     LoRaMacHeader_t  macHdr;
03594 
03595     if( mlmeRequest == NULL )
03596     {
03597         return LORAMAC_STATUS_PARAMETER_INVALID ;
03598     }
03599     if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
03600     {
03601         return LORAMAC_STATUS_BUSY ;
03602     }
03603 
03604     memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
03605 
03606     MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
03607 
03608     switch( mlmeRequest->Type  )
03609     {
03610         case MLME_JOIN :
03611         {
03612             if( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED )
03613             {
03614                 return LORAMAC_STATUS_BUSY ;
03615             }
03616 
03617             MlmeConfirm.MlmeRequest = mlmeRequest->Type ;
03618 
03619             if( ( mlmeRequest->Req.Join .DevEui  == NULL ) ||
03620                 ( mlmeRequest->Req.Join .AppEui  == NULL ) ||
03621                 ( mlmeRequest->Req.Join .AppKey  == NULL ) )
03622             {
03623                 return LORAMAC_STATUS_PARAMETER_INVALID ;
03624             }
03625 
03626             LoRaMacFlags.Bits.MlmeReq  = 1;
03627 
03628             LoRaMacDevEui = mlmeRequest->Req.Join .DevEui ;
03629             LoRaMacAppEui = mlmeRequest->Req.Join .AppEui ;
03630             LoRaMacAppKey = mlmeRequest->Req.Join .AppKey ;
03631 
03632             macHdr.Value  = 0;
03633             macHdr.Bits.MType   = FRAME_TYPE_JOIN_REQ ;
03634 
03635             IsLoRaMacNetworkJoined = false;
03636 
03637 #if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
03638 
03639             static uint8_t drSwitch = 0;
03640 
03641             if( ( ++drSwitch & 0x01 ) == 0x01 )
03642             {
03643                 ChannelsDatarate = DR_0;
03644             }
03645             else
03646             {
03647                 ChannelsDatarate = DR_4;
03648             }
03649 #endif
03650 
03651             status = Send( &macHdr, 0, NULL, 0 );
03652             break;
03653         }
03654         case MLME_LINK_CHECK :
03655         {
03656             LoRaMacFlags.Bits.MlmeReq  = 1;
03657             // LoRaMac will send this command piggy-pack
03658             MlmeConfirm.MlmeRequest = mlmeRequest->Type ;
03659 
03660             status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ , 0, 0 );
03661             break;
03662         }
03663         default:
03664             break;
03665     }
03666 
03667     if( status != LORAMAC_STATUS_OK  )
03668     {
03669         NodeAckRequested = false;
03670         LoRaMacFlags.Bits.MlmeReq  = 0;
03671     }
03672 
03673     return status;
03674 }
03675 
03676 LoRaMacStatus_t  LoRaMacMcpsRequest( McpsReq_t  *mcpsRequest )
03677 {
03678     LoRaMacStatus_t  status = LORAMAC_STATUS_SERVICE_UNKNOWN ;
03679     LoRaMacHeader_t  macHdr;
03680     uint8_t fPort = 0;
03681     void *fBuffer;
03682     uint16_t fBufferSize;
03683     int8_t datarate;
03684     bool readyToSend = false;
03685 
03686     if( mcpsRequest == NULL )
03687     {
03688         return LORAMAC_STATUS_PARAMETER_INVALID ;
03689     }
03690     if( ( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) ||
03691         ( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED ) )
03692     {
03693         return LORAMAC_STATUS_BUSY ;
03694     }
03695 
03696     macHdr.Value  = 0;
03697     memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) );
03698     McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR ;
03699 
03700     switch( mcpsRequest->Type  )
03701     {
03702         case MCPS_UNCONFIRMED :
03703         {
03704             readyToSend = true;
03705             AckTimeoutRetries = 1;
03706 
03707             macHdr.Bits.MType  = FRAME_TYPE_DATA_UNCONFIRMED_UP ;
03708             fPort = mcpsRequest->Req.Unconfirmed .fPort ;
03709             fBuffer = mcpsRequest->Req.Unconfirmed .fBuffer ;
03710             fBufferSize = mcpsRequest->Req.Unconfirmed .fBufferSize ;
03711             datarate = mcpsRequest->Req.Unconfirmed .Datarate ;
03712             break;
03713         }
03714         case MCPS_CONFIRMED :
03715         {
03716             readyToSend = true;
03717             AckTimeoutRetriesCounter = 1;
03718             AckTimeoutRetries = mcpsRequest->Req.Confirmed .NbTrials ;
03719 
03720             macHdr.Bits.MType  = FRAME_TYPE_DATA_CONFIRMED_UP ;
03721             fPort = mcpsRequest->Req.Confirmed .fPort ;
03722             fBuffer = mcpsRequest->Req.Confirmed .fBuffer ;
03723             fBufferSize = mcpsRequest->Req.Confirmed .fBufferSize ;
03724             datarate = mcpsRequest->Req.Confirmed .Datarate ;
03725             break;
03726         }
03727         case MCPS_PROPRIETARY :
03728         {
03729             readyToSend = true;
03730             AckTimeoutRetries = 1;
03731 
03732             macHdr.Bits.MType  = FRAME_TYPE_PROPRIETARY ;
03733             fBuffer = mcpsRequest->Req.Proprietary .fBuffer ;
03734             fBufferSize = mcpsRequest->Req.Proprietary .fBufferSize ;
03735             datarate = mcpsRequest->Req.Proprietary .Datarate ;
03736             break;
03737         }
03738         default:
03739             break;
03740     }
03741 
03742     if( readyToSend == true )
03743     {
03744         if( AdrCtrlOn == false )
03745         {
03746             if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true )
03747             {
03748                 ChannelsDatarate = datarate;
03749             }
03750             else
03751             {
03752                 return LORAMAC_STATUS_PARAMETER_INVALID ;
03753             }
03754         }
03755 
03756         status = Send( &macHdr, fPort, fBuffer, fBufferSize );
03757         if( status == LORAMAC_STATUS_OK  )
03758         {
03759             McpsConfirm.McpsRequest = mcpsRequest->Type ;
03760             LoRaMacFlags.Bits.McpsReq  = 1;
03761         }
03762         else
03763         {
03764             NodeAckRequested = false;
03765         }
03766     }
03767 
03768     return status;
03769 }
03770 
03771 void LoRaMacTestRxWindowsOn( bool enable )
03772 {
03773     IsRxWindowsEnabled = enable;
03774 }
03775 
03776 void LoRaMacTestSetMic( uint16_t txPacketCounter )
03777 {
03778     UpLinkCounter = txPacketCounter;
03779     IsUpLinkCounterFixed = true;
03780 }
03781 
03782 void LoRaMacTestSetDutyCycleOn( bool enable )
03783 {
03784     DutyCycleOn = enable;
03785 }