LoRaWAN MAC layer implementation

Dependents:   LoRaWAN-demo-72_tjm LoRaWAN-demo-72_jlc LoRaWAN-demo-elmo frdm_LoRa_Connect_Woodstream_Demo_tjm ... more

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