Fork of Semtech LoRaWAN stack

Fork of LoRaWAN-lib by canuck lehead

Files at this revision

API Documentation at this revision

Comitter:
Shaun Nelson
Date:
Mon Oct 15 09:15:20 2018 -0400
Branch:
SenetNetTool
Parent:
36:fc9baa35ae1a
Commit message:
Removed static type for up/down counters for access from external code

Changed in this revision

LoRaMac-board.h Show annotated file Show diff for this revision Revisions of this file
LoRaMac.cpp Show annotated file Show diff for this revision Revisions of this file
LoRaMac.cpp.orig Show diff for this revision Revisions of this file
diff -r fc9baa35ae1a -r 8b9e6442a02a LoRaMac-board.h
--- a/LoRaMac-board.h	Tue Aug 08 11:21:18 2017 -0400
+++ b/LoRaMac-board.h	Mon Oct 15 09:15:20 2018 -0400
@@ -26,462 +26,486 @@
  * \param[IN] channelIndex Channel index 1 based
  * \retval channelMask
  */
-#define LC( channelIndex )            ( uint16_t )( 1 << ( channelIndex - 1 ) )
+#define LC(channelIndex) (uint16_t)(1 << (channelIndex - 1))
 
-#if defined( USE_BAND_433 )
+#if defined(USE_BAND_433)
 
 /*!
  * LoRaMac maximum number of channels
  */
-#define LORA_MAX_NB_CHANNELS                        16
+#define LORA_MAX_NB_CHANNELS 16
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MIN_DATARATE                     DR_0
+#define LORAMAC_TX_MIN_DATARATE DR_0
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MAX_DATARATE                     DR_7
+#define LORAMAC_TX_MAX_DATARATE DR_7
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MIN_DATARATE                     DR_0
+#define LORAMAC_RX_MIN_DATARATE DR_0
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MAX_DATARATE                     DR_7
+#define LORAMAC_RX_MAX_DATARATE DR_7
 
 /*!
  * Default datarate used by the node
  */
-#define LORAMAC_DEFAULT_DATARATE                    DR_0
+#define LORAMAC_DEFAULT_DATARATE DR_0
 
 /*!
  * Minimal Rx1 receive datarate offset
  */
-#define LORAMAC_MIN_RX1_DR_OFFSET                   0
+#define LORAMAC_MIN_RX1_DR_OFFSET 0
 
 /*!
  * Maximal Rx1 receive datarate offset
  */
-#define LORAMAC_MAX_RX1_DR_OFFSET                   5
+#define LORAMAC_MAX_RX1_DR_OFFSET 5
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MIN_TX_POWER                        TX_POWER_M5_DBM
+#define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MAX_TX_POWER                        TX_POWER_10_DBM
+#define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM
 
 /*!
  * Default Tx output power used by the node
  */
-#define LORAMAC_DEFAULT_TX_POWER                    TX_POWER_10_DBM
+#define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM
 
 /*!
  * LoRaMac TxPower definition
  */
-#define TX_POWER_10_DBM                             0
-#define TX_POWER_07_DBM                             1
-#define TX_POWER_04_DBM                             2
-#define TX_POWER_01_DBM                             3
-#define TX_POWER_M2_DBM                             4
-#define TX_POWER_M5_DBM                             5
+#define TX_POWER_10_DBM 0
+#define TX_POWER_07_DBM 1
+#define TX_POWER_04_DBM 2
+#define TX_POWER_01_DBM 3
+#define TX_POWER_M2_DBM 4
+#define TX_POWER_M5_DBM 5
 
 /*!
  * LoRaMac datarates definition
  */
-#define DR_0                                        0  // SF12 - BW125
-#define DR_1                                        1  // SF11 - BW125
-#define DR_2                                        2  // SF10 - BW125
-#define DR_3                                        3  // SF9  - BW125
-#define DR_4                                        4  // SF8  - BW125
-#define DR_5                                        5  // SF7  - BW125
-#define DR_6                                        6  // SF7  - BW250
-#define DR_7                                        7  // FSK
+#define DR_0 0  // SF12 - BW125
+#define DR_1 1  // SF11 - BW125
+#define DR_2 2  // SF10 - BW125
+#define DR_3 3  // SF9  - BW125
+#define DR_4 4  // SF8  - BW125
+#define DR_5 5  // SF7  - BW125
+#define DR_6 6  // SF7  - BW250
+#define DR_7 7  // FSK
 
 /*!
  * Second reception window channel definition.
  */
 // Channel = { Frequency [Hz], Datarate }
-#define RX_WND_2_CHANNEL                                  { 434665000, DR_0 }
+#define RX_WND_2_CHANNEL \
+  { 434665000, DR_0 }
 
 /*!
  * LoRaMac maximum number of bands
  */
-#define LORA_MAX_NB_BANDS                           1
+#define LORA_MAX_NB_BANDS 1
 
 // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
-#define BAND0              { 100, TX_POWER_10_DBM, 0,  0 } //  1.0 %
+#define BAND0 \
+  { 100, TX_POWER_10_DBM, 0, 0 }  //  1.0 %
 
 /*!
  * LoRaMac default channels
  */
 // Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
-#define LC1                { 433175000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
-#define LC2                { 433375000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
-#define LC3                { 433575000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC1 \
+  { 433175000, {((DR_5 << 4) | DR_0)}, 0 }
+#define LC2 \
+  { 433375000, {((DR_5 << 4) | DR_0)}, 0 }
+#define LC3 \
+  { 433575000, {((DR_5 << 4) | DR_0)}, 0 }
 
 /*!
  * LoRaMac duty cycle for the join procedure
  */
-#define JOIN_DC            1000
+#define JOIN_DC 1000
 
 /*!
  * LoRaMac channels which are allowed for the join procedure
  */
-#define JOIN_CHANNELS      ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
+#define JOIN_CHANNELS (uint16_t)(LC(1) | LC(2) | LC(3))
 
-#elif defined( USE_BAND_780 )
+#elif defined(USE_BAND_780)
 
 /*!
  * LoRaMac maximum number of channels
  */
-#define LORA_MAX_NB_CHANNELS                        16
+#define LORA_MAX_NB_CHANNELS 16
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MIN_DATARATE                     DR_0
+#define LORAMAC_TX_MIN_DATARATE DR_0
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MAX_DATARATE                     DR_7
+#define LORAMAC_TX_MAX_DATARATE DR_7
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MIN_DATARATE                     DR_0
+#define LORAMAC_RX_MIN_DATARATE DR_0
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MAX_DATARATE                     DR_7
+#define LORAMAC_RX_MAX_DATARATE DR_7
 
 /*!
  * Default datarate used by the node
  */
-#define LORAMAC_DEFAULT_DATARATE                    DR_0
+#define LORAMAC_DEFAULT_DATARATE DR_0
 
 /*!
  * Minimal Rx1 receive datarate offset
  */
-#define LORAMAC_MIN_RX1_DR_OFFSET                   0
+#define LORAMAC_MIN_RX1_DR_OFFSET 0
 
 /*!
  * Maximal Rx1 receive datarate offset
  */
-#define LORAMAC_MAX_RX1_DR_OFFSET                   5
+#define LORAMAC_MAX_RX1_DR_OFFSET 5
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MIN_TX_POWER                        TX_POWER_M5_DBM
+#define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MAX_TX_POWER                        TX_POWER_10_DBM
+#define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM
 
 /*!
  * Default Tx output power used by the node
  */
-#define LORAMAC_DEFAULT_TX_POWER                    TX_POWER_10_DBM
+#define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM
 
 /*!
  * LoRaMac TxPower definition
  */
-#define TX_POWER_10_DBM                             0
-#define TX_POWER_07_DBM                             1
-#define TX_POWER_04_DBM                             2
-#define TX_POWER_01_DBM                             3
-#define TX_POWER_M2_DBM                             4
-#define TX_POWER_M5_DBM                             5
+#define TX_POWER_10_DBM 0
+#define TX_POWER_07_DBM 1
+#define TX_POWER_04_DBM 2
+#define TX_POWER_01_DBM 3
+#define TX_POWER_M2_DBM 4
+#define TX_POWER_M5_DBM 5
 
 /*!
  * LoRaMac datarates definition
  */
-#define DR_0                                        0  // SF12 - BW125
-#define DR_1                                        1  // SF11 - BW125
-#define DR_2                                        2  // SF10 - BW125
-#define DR_3                                        3  // SF9  - BW125
-#define DR_4                                        4  // SF8  - BW125
-#define DR_5                                        5  // SF7  - BW125
-#define DR_6                                        6  // SF7  - BW250
-#define DR_7                                        7  // FSK
+#define DR_0 0  // SF12 - BW125
+#define DR_1 1  // SF11 - BW125
+#define DR_2 2  // SF10 - BW125
+#define DR_3 3  // SF9  - BW125
+#define DR_4 4  // SF8  - BW125
+#define DR_5 5  // SF7  - BW125
+#define DR_6 6  // SF7  - BW250
+#define DR_7 7  // FSK
 
 /*!
  * Second reception window channel definition.
  */
 // Channel = { Frequency [Hz], Datarate }
-#define RX_WND_2_CHANNEL                                  { 786000000, DR_0 }
+#define RX_WND_2_CHANNEL \
+  { 786000000, DR_0 }
 
 /*!
  * LoRaMac maximum number of bands
  */
-#define LORA_MAX_NB_BANDS                           1
+#define LORA_MAX_NB_BANDS 1
 
 // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
-#define BAND0              { 100, TX_POWER_10_DBM, 0,  0 } //  1.0 %
+#define BAND0 \
+  { 100, TX_POWER_10_DBM, 0, 0 }  //  1.0 %
 
 /*!
  * LoRaMac default channels
  */
 // Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
-#define LC1                { 779500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
-#define LC2                { 779700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
-#define LC3                { 779900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 }
+#define LC1 \
+  { 779500000, {((DR_5 << 4) | DR_0)}, 0 }
+#define LC2 \
+  { 779700000, {((DR_5 << 4) | DR_0)}, 0 }
+#define LC3 \
+  { 779900000, {((DR_5 << 4) | DR_0)}, 0 }
 
 /*!
  * LoRaMac duty cycle for the join procedure
  */
-#define JOIN_DC            1000
+#define JOIN_DC 1000
 
 /*!
  * LoRaMac channels which are allowed for the join procedure
  */
-#define JOIN_CHANNELS      ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
+#define JOIN_CHANNELS (uint16_t)(LC(1) | LC(2) | LC(3))
 
-#elif defined( USE_BAND_868 )
+#elif defined(USE_BAND_868)
 
 /*!
  * LoRaMac maximum number of channels
  */
-#define LORA_MAX_NB_CHANNELS                        16
+#define LORA_MAX_NB_CHANNELS 16
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MIN_DATARATE                     DR_0
+#define LORAMAC_TX_MIN_DATARATE DR_0
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MAX_DATARATE                     DR_7
+#define LORAMAC_TX_MAX_DATARATE DR_7
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MIN_DATARATE                     DR_0
+#define LORAMAC_RX_MIN_DATARATE DR_0
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MAX_DATARATE                     DR_7
+#define LORAMAC_RX_MAX_DATARATE DR_7
 
 /*!
  * Default datarate used by the node
  */
-#define LORAMAC_DEFAULT_DATARATE                    DR_0
+#define LORAMAC_DEFAULT_DATARATE DR_0
 
 /*!
  * Minimal Rx1 receive datarate offset
  */
-#define LORAMAC_MIN_RX1_DR_OFFSET                   0
+#define LORAMAC_MIN_RX1_DR_OFFSET 0
 
 /*!
  * Maximal Rx1 receive datarate offset
  */
-#define LORAMAC_MAX_RX1_DR_OFFSET                   5
+#define LORAMAC_MAX_RX1_DR_OFFSET 5
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MIN_TX_POWER                        TX_POWER_02_DBM
+#define LORAMAC_MIN_TX_POWER TX_POWER_02_DBM
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MAX_TX_POWER                        TX_POWER_20_DBM
+#define LORAMAC_MAX_TX_POWER TX_POWER_20_DBM
 
 /*!
  * Default Tx output power used by the node
  */
-#define LORAMAC_DEFAULT_TX_POWER                    TX_POWER_14_DBM
+#define LORAMAC_DEFAULT_TX_POWER TX_POWER_14_DBM
 
 /*!
  * LoRaMac TxPower definition
  */
-#define TX_POWER_20_DBM                             0
-#define TX_POWER_14_DBM                             1
-#define TX_POWER_11_DBM                             2
-#define TX_POWER_08_DBM                             3
-#define TX_POWER_05_DBM                             4
-#define TX_POWER_02_DBM                             5
+#define TX_POWER_20_DBM 0
+#define TX_POWER_14_DBM 1
+#define TX_POWER_11_DBM 2
+#define TX_POWER_08_DBM 3
+#define TX_POWER_05_DBM 4
+#define TX_POWER_02_DBM 5
 
 /*!
  * LoRaMac datarates definition
  */
-#define DR_0                                        0  // SF12 - BW125
-#define DR_1                                        1  // SF11 - BW125
-#define DR_2                                        2  // SF10 - BW125
-#define DR_3                                        3  // SF9  - BW125
-#define DR_4                                        4  // SF8  - BW125
-#define DR_5                                        5  // SF7  - BW125
-#define DR_6                                        6  // SF7  - BW250
-#define DR_7                                        7  // FSK
+#define DR_0 0  // SF12 - BW125
+#define DR_1 1  // SF11 - BW125
+#define DR_2 2  // SF10 - BW125
+#define DR_3 3  // SF9  - BW125
+#define DR_4 4  // SF8  - BW125
+#define DR_5 5  // SF7  - BW125
+#define DR_6 6  // SF7  - BW250
+#define DR_7 7  // FSK
 
 /*!
  * Second reception window channel definition.
  */
 // Channel = { Frequency [Hz], Datarate }
-#define RX_WND_2_CHANNEL                                  { 869525000, DR_0 }
+#define RX_WND_2_CHANNEL \
+  { 869525000, DR_0 }
 
 /*!
  * LoRaMac maximum number of bands
  */
-#define LORA_MAX_NB_BANDS                           5
+#define LORA_MAX_NB_BANDS 5
 
 /*!
  * LoRaMac EU868 default bands
  */
-typedef enum
-{
-    BAND_G1_0,
-    BAND_G1_1,
-    BAND_G1_2,
-    BAND_G1_3,
-    BAND_G1_4,
-}BandId_t;
+typedef enum {
+  BAND_G1_0,
+  BAND_G1_1,
+  BAND_G1_2,
+  BAND_G1_3,
+  BAND_G1_4,
+} BandId_t;
 
 // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
-#define BAND0              { 100 , TX_POWER_14_DBM, 0,  0 } //  1.0 %
-#define BAND1              { 100 , TX_POWER_14_DBM, 0,  0 } //  1.0 %
-#define BAND2              { 1000, TX_POWER_14_DBM, 0,  0 } //  0.1 %
-#define BAND3              { 10  , TX_POWER_14_DBM, 0,  0 } // 10.0 %
-#define BAND4              { 100 , TX_POWER_14_DBM, 0,  0 } //  1.0 %
+#define BAND0 \
+  { 100, TX_POWER_14_DBM, 0, 0 }  //  1.0 %
+#define BAND1 \
+  { 100, TX_POWER_14_DBM, 0, 0 }  //  1.0 %
+#define BAND2 \
+  { 1000, TX_POWER_14_DBM, 0, 0 }  //  0.1 %
+#define BAND3 \
+  { 10, TX_POWER_14_DBM, 0, 0 }  // 10.0 %
+#define BAND4 \
+  { 100, TX_POWER_14_DBM, 0, 0 }  //  1.0 %
 
 /*!
  * LoRaMac default channels
  */
 // Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band }
-#define LC1                { 868100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
-#define LC2                { 868300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
-#define LC3                { 868500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 }
+#define LC1 \
+  { 868100000, {((DR_5 << 4) | DR_0)}, 1 }
+#define LC2 \
+  { 868300000, {((DR_5 << 4) | DR_0)}, 1 }
+#define LC3 \
+  { 868500000, {((DR_5 << 4) | DR_0)}, 1 }
 
 /*!
  * LoRaMac duty cycle for the join procedure
  */
-#define JOIN_DC            1000
+#define JOIN_DC 1000
 
 /*!
  * LoRaMac channels which are allowed for the join procedure
  */
-#define JOIN_CHANNELS      ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) )
+#define JOIN_CHANNELS (uint16_t)(LC(1) | LC(2) | LC(3))
 
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+#elif defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
 
 /*!
  * LoRaMac maximum number of channels
  */
-#define LORA_MAX_NB_CHANNELS                        72
+#define LORA_MAX_NB_CHANNELS 72
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MIN_DATARATE                     DR_0
+#define LORAMAC_TX_MIN_DATARATE DR_0
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_TX_MAX_DATARATE                     DR_4
+#define LORAMAC_TX_MAX_DATARATE DR_4
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MIN_DATARATE                     DR_8
+#define LORAMAC_RX_MIN_DATARATE DR_8
 
 /*!
  * Minimal datarate that can be used by the node
  */
-#define LORAMAC_RX_MAX_DATARATE                     DR_13
+#define LORAMAC_RX_MAX_DATARATE DR_13
 
 /*!
  * Default datarate used by the node
  */
-#define LORAMAC_DEFAULT_DATARATE                    DR_0
+#define LORAMAC_DEFAULT_DATARATE DR_0
 
 /*!
  * Minimal Rx1 receive datarate offset
  */
-#define LORAMAC_MIN_RX1_DR_OFFSET                   0
+#define LORAMAC_MIN_RX1_DR_OFFSET 0
 
 /*!
  * Maximal Rx1 receive datarate offset
  */
-#define LORAMAC_MAX_RX1_DR_OFFSET                   3
+#define LORAMAC_MAX_RX1_DR_OFFSET 3
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MIN_TX_POWER                        TX_POWER_10_DBM
+#define LORAMAC_MIN_TX_POWER TX_POWER_2_DBM
 
 /*!
  * Minimal Tx output power that can be used by the node
  */
-#define LORAMAC_MAX_TX_POWER                        TX_POWER_30_DBM
+#define LORAMAC_MAX_TX_POWER TX_POWER_30_DBM
 
 /*!
  * Default Tx output power used by the node
  */
-#define LORAMAC_DEFAULT_TX_POWER                    TX_POWER_30_DBM
+#define LORAMAC_DEFAULT_TX_POWER TX_POWER_30_DBM
 
 /*!
  * LoRaMac TxPower definition
  */
-#define TX_POWER_30_DBM                             0
-#define TX_POWER_28_DBM                             1
-#define TX_POWER_26_DBM                             2
-#define TX_POWER_24_DBM                             3
-#define TX_POWER_22_DBM                             4
-#define TX_POWER_20_DBM                             5
-#define TX_POWER_18_DBM                             6
-#define TX_POWER_16_DBM                             7
-#define TX_POWER_14_DBM                             8
-#define TX_POWER_12_DBM                             9
-#define TX_POWER_10_DBM                             10
+#define TX_POWER_30_DBM 0
+#define TX_POWER_28_DBM 1
+#define TX_POWER_26_DBM 2
+#define TX_POWER_24_DBM 3
+#define TX_POWER_22_DBM 4
+#define TX_POWER_20_DBM 5
+#define TX_POWER_18_DBM 6
+#define TX_POWER_16_DBM 7
+#define TX_POWER_14_DBM 8
+#define TX_POWER_12_DBM 9
+#define TX_POWER_10_DBM 10
+#define TX_POWER_8_DBM 11
+#define TX_POWER_6_DBM 12
+#define TX_POWER_4_DBM 13
+#define TX_POWER_2_DBM 14
 
 /*!
  * LoRaMac datarates definition
  */
-#define DR_0                                        0  // SF10 - BW125 |
-#define DR_1                                        1  // SF9  - BW125 |
-#define DR_2                                        2  // SF8  - BW125 +-> Up link
-#define DR_3                                        3  // SF7  - BW125 |
-#define DR_4                                        4  // SF8  - BW500 |
-#define DR_5                                        5  // RFU
-#define DR_6                                        6  // RFU
-#define DR_7                                        7  // RFU
-#define DR_8                                        8  // SF12 - BW500 |
-#define DR_9                                        9  // SF11 - BW500 |
-#define DR_10                                       10 // SF10 - BW500 |
-#define DR_11                                       11 // SF9  - BW500 |
-#define DR_12                                       12 // SF8  - BW500 +-> Down link
-#define DR_13                                       13 // SF7  - BW500 |
-#define DR_14                                       14 // RFU          |
-#define DR_15                                       15 // RFU          |
+#define DR_0 0    // SF10 - BW125 |
+#define DR_1 1    // SF9  - BW125 |
+#define DR_2 2    // SF8  - BW125 +-> Up link
+#define DR_3 3    // SF7  - BW125 |
+#define DR_4 4    // SF8  - BW500 |
+#define DR_5 5    // RFU
+#define DR_6 6    // RFU
+#define DR_7 7    // RFU
+#define DR_8 8    // SF12 - BW500 |
+#define DR_9 9    // SF11 - BW500 |
+#define DR_10 10  // SF10 - BW500 |
+#define DR_11 11  // SF9  - BW500 |
+#define DR_12 12  // SF8  - BW500 +-> Down link
+#define DR_13 13  // SF7  - BW500 |
+#define DR_14 14  // RFU          |
+#define DR_15 15  // RFU          |
 
 /*!
  * Second reception window channel definition.
  */
 // Channel = { Frequency [Hz], Datarate }
-#define RX_WND_2_CHANNEL                                  { 923300000, DR_8 }
+#define RX_WND_2_CHANNEL \
+  { 923300000, DR_8 }
 
 /*!
  * LoRaMac maximum number of bands
  */
-#define LORA_MAX_NB_BANDS                           1
+#define LORA_MAX_NB_BANDS 1
 
 // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff }
-#define BAND0              { 1, TX_POWER_20_DBM, 0,  0 } //  100.0 %
+#define BAND0 \
+  { 1, TX_POWER_20_DBM, 0, 0 }  //  100.0 %
 
 /*!
  * LoRaMac default channels
@@ -507,7 +531,7 @@
  * \endcode
  */
 #else
-    #error "Please define a frequency band in the compiler options."
+#error "Please define a frequency band in the compiler options."
 #endif
 
-#endif // __LORAMAC_BOARD_H__
+#endif  // __LORAMAC_BOARD_H__
diff -r fc9baa35ae1a -r 8b9e6442a02a LoRaMac.cpp
--- a/LoRaMac.cpp	Tue Aug 08 11:21:18 2017 -0400
+++ b/LoRaMac.cpp	Mon Oct 15 09:15:20 2018 -0400
@@ -15,7 +15,8 @@
 
 License: Revised BSD License, see LICENSE.TXT file include in the project
 
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
+Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel
+Jäckle ( STACKFORCE )
 */
 #include "board.h"
 
@@ -26,19 +27,20 @@
 /*!
  * Maximum PHY layer payload size
  */
-#define LORAMAC_PHY_MAXPAYLOAD                      255
+#define LORAMAC_PHY_MAXPAYLOAD 255
 
 /*!
  * Maximum MAC commands buffer size
  */
-#define LORA_MAC_COMMAND_MAX_LENGTH                 15
+#define LORA_MAC_COMMAND_MAX_LENGTH 15
 
 /*!
  * FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
  * in RxWindowSetup function.
- * Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD
+ * Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater +
+ * LORA_MAC_FRMPAYLOAD_OVERHEAD
  */
-#define LORA_MAC_FRMPAYLOAD_OVERHEAD                13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
+#define LORA_MAC_FRMPAYLOAD_OVERHEAD 13  // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
 
 /*!
  * Minimum number of available channels in Frequency Hopping Mode
@@ -50,39 +52,32 @@
  */
 #define HYBRD_CHNLS_MIN 4
 
-
 /*!
  * Device IEEE EUI
  */
-static uint8_t *LoRaMacDevEui;
+static uint8_t* LoRaMacDevEui;
 
 /*!
  * Application IEEE EUI
  */
-static uint8_t *LoRaMacAppEui;
+static uint8_t* LoRaMacAppEui;
 
 /*!
  * AES encryption/decryption cipher application key
  */
-static uint8_t *LoRaMacAppKey;
+static uint8_t* LoRaMacAppKey;
 
 /*!
  * AES encryption/decryption cipher network session key
  */
-static uint8_t LoRaMacNwkSKey[] =
-{
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
+static uint8_t LoRaMacNwkSKey[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 /*!
  * AES encryption/decryption cipher application session key
  */
-static uint8_t LoRaMacAppSKey[] =
-{
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
+static uint8_t LoRaMacAppSKey[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
 /*!
  * Device nonce is a random value extracted by issuing a sequence of RSSI
@@ -103,7 +98,7 @@
 /*!
  * Multicast channels linked list
  */
-static MulticastParams_t *MulticastChannels = NULL;
+static MulticastParams_t* MulticastChannels = NULL;
 
 /*!
  * Actual device class
@@ -140,13 +135,14 @@
  * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
  * Only the 16 LSB bits are sent
  */
-static uint32_t UpLinkCounter = 1;
+uint32_t UpLinkCounter = 1;
 
 /*!
- * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
+ * LoRaMAC frame counter. Each time a packet is received the counter is
+ * incremented.
  * Only the 16 LSB bits are received
  */
-static uint32_t DownLinkCounter = 0;
+uint32_t DownLinkCounter = 0;
 
 /*!
  * IsPacketCounterFixed enables the MIC field tests by fixing the
@@ -181,7 +177,8 @@
 static bool NodeAckRequested = false;
 
 /*!
- * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
+ * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable
+ * indicates
  * if the ACK bit must be set for the next transmission
  */
 static bool SrvAckRequested = false;
@@ -211,174 +208,159 @@
  */
 static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
 
-#if defined( USE_BAND_433 )
+#if defined(USE_BAND_433)
 /*!
  * Data rates table definition
  */
-const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
+const uint8_t Datarates[] = {12, 11, 10, 9, 8, 7, 7, 50};
 
 /*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ * Maximum payload with respect to the datarate index. Cannot operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
+const uint8_t MaxPayloadOfDatarate[] = {59, 59, 59, 123, 250, 250, 250, 250};
 
 /*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
+ * Maximum payload with respect to the datarate index. Can operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = {59, 59, 59, 123, 230, 230, 230, 230};
 
 /*!
  * Tx output powers table definition
  */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
+const int8_t TxPowers[] = {20, 14, 11, 8, 5, 2};
 
 /*!
  * LoRaMac bands
  */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
+static Band_t Bands[LORA_MAX_NB_BANDS] = {
+  BAND0,
 };
 
 /*!
  * LoRaMAC channels
  */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
-    LC1,
-    LC2,
-    LC3,
+static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] = {
+  LC1, LC2, LC3,
 };
-#elif defined( USE_BAND_780 )
+#elif defined(USE_BAND_780)
 /*!
  * Data rates table definition
  */
-const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
+const uint8_t Datarates[] = {12, 11, 10, 9, 8, 7, 7, 50};
 
 /*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ * Maximum payload with respect to the datarate index. Cannot operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
+const uint8_t MaxPayloadOfDatarate[] = {59, 59, 59, 123, 250, 250, 250, 250};
 
 /*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
+ * Maximum payload with respect to the datarate index. Can operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = {59, 59, 59, 123, 230, 230, 230, 230};
 
 /*!
  * Tx output powers table definition
  */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
+const int8_t TxPowers[] = {20, 14, 11, 8, 5, 2};
 
 /*!
  * LoRaMac bands
  */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
+static Band_t Bands[LORA_MAX_NB_BANDS] = {
+  BAND0,
 };
 
 /*!
  * LoRaMAC channels
  */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
-    LC1,
-    LC2,
-    LC3,
+static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] = {
+  LC1, LC2, LC3,
 };
-#elif defined( USE_BAND_868 )
+#elif defined(USE_BAND_868)
 /*!
  * Data rates table definition
  */
-const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
+const uint8_t Datarates[] = {12, 11, 10, 9, 8, 7, 7, 50};
 
 /*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ * Maximum payload with respect to the datarate index. Cannot operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
+const uint8_t MaxPayloadOfDatarate[] = {51, 51, 51, 115, 242, 242, 242, 242};
 
 /*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
+ * Maximum payload with respect to the datarate index. Can operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = {51, 51, 51, 115, 222, 222, 222, 222};
 
 /*!
  * Tx output powers table definition
  */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
+const int8_t TxPowers[] = {20, 14, 11, 8, 5, 2};
 
 /*!
  * LoRaMac bands
  */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
-    BAND1,
-    BAND2,
-    BAND3,
-    BAND4,
+static Band_t Bands[LORA_MAX_NB_BANDS] = {
+  BAND0, BAND1, BAND2, BAND3, BAND4,
 };
 
 /*!
  * LoRaMAC channels
  */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
-    LC1,
-    LC2,
-    LC3,
+static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] = {
+  LC1, LC2, LC3,
 };
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+#elif defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
 /*!
  * Data rates table definition
  */
-const uint8_t Datarates[]  = { 10, 9, 8,  7,  8,  0,  0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
+const uint8_t Datarates[] = {10, 9, 8, 7, 8, 0, 0, 0, 12, 11, 10, 9, 8, 7, 0, 0};
 
 /*!
  * Up/Down link data rates offset definition
  */
-const uint8_t datarateOffsets[16][4] =
-{
-    { DR_10, DR_9 , DR_8 , DR_8  }, // DR_0
-    { DR_11, DR_10, DR_9 , DR_8  }, // DR_1
-    { DR_12, DR_11, DR_10, DR_9  }, // DR_2
-    { DR_13, DR_12, DR_11, DR_10 }, // DR_3
-    { DR_13, DR_13, DR_12, DR_11 }, // DR_4
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { DR_8 , DR_8 , DR_8 , DR_8  },
-    { DR_9 , DR_8 , DR_8 , DR_8  },
-    { DR_10, DR_9 , DR_8 , DR_8  },
-    { DR_11, DR_10, DR_9 , DR_8  },
-    { DR_12, DR_11, DR_10, DR_9  },
-    { DR_13, DR_12, DR_11, DR_10 },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
+const uint8_t datarateOffsets[16][4] = {
+  {DR_10, DR_9, DR_8, DR_8},     // DR_0
+  {DR_11, DR_10, DR_9, DR_8},    // DR_1
+  {DR_12, DR_11, DR_10, DR_9},   // DR_2
+  {DR_13, DR_12, DR_11, DR_10},  // DR_3
+  {DR_13, DR_13, DR_12, DR_11},  // DR_4
+  {0xFF, 0xFF, 0xFF, 0xFF},     {0xFF, 0xFF, 0xFF, 0xFF},    {0xFF, 0xFF, 0xFF, 0xFF},
+  {DR_8, DR_8, DR_8, DR_8},     {DR_9, DR_8, DR_8, DR_8},    {DR_10, DR_9, DR_8, DR_8},
+  {DR_11, DR_10, DR_9, DR_8},   {DR_12, DR_11, DR_10, DR_9}, {DR_13, DR_12, DR_11, DR_10},
+  {0xFF, 0xFF, 0xFF, 0xFF},     {0xFF, 0xFF, 0xFF, 0xFF},
 };
 
 /*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
+ * Maximum payload with respect to the datarate index. Cannot operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 126, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
+const uint8_t MaxPayloadOfDatarate[] = {11, 53,  126, 242, 242, 0,   0, 0,
+                                        53, 129, 242, 242, 242, 242, 0, 0};
 
 /*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
+ * Maximum payload with respect to the datarate index. Can operate with
+ * repeater.
  */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 126, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
+const uint8_t MaxPayloadOfDatarateRepeater[] = {11, 53,  126, 242, 242, 0,   0, 0,
+                                                33, 109, 222, 222, 222, 222, 0, 0};
 
 /*!
  * Tx output powers table definition
  */
-const int8_t TxPowers[]    = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };
+const int8_t TxPowers[] = {30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2};
 
 /*!
  * LoRaMac bands
  */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
+static Band_t Bands[LORA_MAX_NB_BANDS] = {
+  BAND0,
 };
 
 /*!
@@ -391,33 +373,34 @@
  */
 static uint16_t ChannelsMaskRemaining[6];
 
-#if defined( USE_BAND_915 ) 
+#if defined(USE_BAND_915)
 /*!
- *  Last join request sub-band 
+ *  Last join request sub-band
  */
 static int8_t LastJoinBlock;
 
 /*!
  * Next join sub-band block
  */
-static uint8_t  NextJoinBlock;
+static uint8_t NextJoinBlock;
+
+/*!
+ * Mask of 125 KHz sub-bands not used for join transmit
+ */
+static uint8_t JoinBlocksRemaining;
 
 /*!
- * Mask of 125 KHz sub-bands not used for join transmit 
+ * Mask of 500 KHz sub-bands not used for join transmit
  */
-static uint8_t  JoinBlocksRemaining;
-
-/*!
- * Mask of 500 KHz sub-bands not used for join transmit 
- */
-static uint8_t  Join500KHzRemaining;
+static uint8_t Join500KHzRemaining;
 
 #ifndef JOIN_BLOCK_ORDER
-#define JOIN_BLOCK_ORDER { -1, -1, -1, -1, -1, -1, -1, -1 }
+#define JOIN_BLOCK_ORDER \
+  { -1, -1, -1, -1, -1, -1, -1, -1 }
 #endif
 
 /*!
- * join sub-band block order 
+ * join sub-band block order
  */
 static int8_t JoinBlock[8] = JOIN_BLOCK_ORDER;
 
@@ -426,21 +409,20 @@
 /*!
  * Defines the first channel for RX window 2 for US band
  */
-#define LORAMAC_FIRST_RX2_CHANNEL           ( (uint32_t) 923.3e6 )
+#define LORAMAC_FIRST_RX2_CHANNEL ((uint32_t)923.3e6)
 
 /*!
  * Defines the last channel for RX window 2 for US band
  */
-#define LORAMAC_LAST_RX2_CHANNEL            ( (uint32_t) 927.5e6 )
+#define LORAMAC_LAST_RX2_CHANNEL ((uint32_t)927.5e6)
 
 /*!
  * Defines the step width of the channels for RX window 2
  */
-#define LORAMAC_STEPWIDTH_RX2_CHANNEL       ( (uint32_t) 600e3 )
-
+#define LORAMAC_STEPWIDTH_RX2_CHANNEL ((uint32_t)600e3)
 
 #else
-    #error "Please define a frequency band in the compiler options."
+#error "Please define a frequency band in the compiler options."
 #endif
 
 /*!
@@ -492,7 +474,7 @@
 /*!
  * Aggregated duty cycle management
  */
-static uint16_t AggregatedDCycle;
+static uint16_t    AggregatedDCycle;
 static TimerTime_t AggregatedLastTxDoneTime;
 static TimerTime_t AggregatedTimeOff;
 
@@ -511,16 +493,15 @@
 /*!
  * LoRaMac internal states
  */
-enum eLoRaMacState
-{
-    MAC_IDLE          = 0x00000000,
-    MAC_TX_RUNNING    = 0x00000001,
-    MAC_RX            = 0x00000002,
-    MAC_ACK_REQ       = 0x00000004,
-    MAC_ACK_RETRY     = 0x00000008,
-    MAC_TX_DELAYED    = 0x00000010,
-    MAC_TX_CONFIG     = 0x00000020,
-    MAC_RX_ABORT      = 0x00000040,
+enum eLoRaMacState {
+  MAC_IDLE       = 0x00000000,
+  MAC_TX_RUNNING = 0x00000001,
+  MAC_RX         = 0x00000002,
+  MAC_ACK_REQ    = 0x00000004,
+  MAC_ACK_RETRY  = 0x00000008,
+  MAC_TX_DELAYED = 0x00000010,
+  MAC_TX_CONFIG  = 0x00000020,
+  MAC_RX_ABORT   = 0x00000040,
 };
 
 /*!
@@ -536,12 +517,12 @@
 /*!
  * LoRaMac upper layer event functions
  */
-static LoRaMacPrimitives_t *LoRaMacPrimitives;
+static LoRaMacPrimitives_t* LoRaMacPrimitives;
 
 /*!
  * LoRaMac upper layer callback functions
  */
-static LoRaMacCallback_t *LoRaMacCallbacks;
+static LoRaMacCallback_t* LoRaMacCallbacks;
 
 /*!
  * Radio events function pointer
@@ -633,12 +614,8 @@
 /*!
  * Join Retransmission back-off configuration
  */
-LoRaMacRetransmissionDCycle_t JoinReTransmitDCycle[JOIN_NB_RETRANSMISSION_DCYCLES] = 
-{
-    JOIN_RETRANSMISSION_DCYCLE1, 
-    JOIN_RETRANSMISSION_DCYCLE2, 
-    JOIN_RETRANSMISSION_DCYCLE3
-};
+LoRaMacRetransmissionDCycle_t JoinReTransmitDCycle[JOIN_NB_RETRANSMISSION_DCYCLES] = {
+  JOIN_RETRANSMISSION_DCYCLE1, JOIN_RETRANSMISSION_DCYCLE2, JOIN_RETRANSMISSION_DCYCLE3};
 
 /*!
  * Uptime of the last sent join request
@@ -646,66 +623,65 @@
 static TimerTime_t LastJoinTxTime;
 
 /*!
- * Aggregated join request time on air 
+ * Aggregated join request time on air
  */
-static TimerTime_t JoinAggTimeOnAir; 
-
+static TimerTime_t JoinAggTimeOnAir;
 
 /*!
  * \brief Function to be executed on Radio Tx Done event
  */
-static void OnRadioTxDone( void );
+static void OnRadioTxDone(void);
 
 /*!
  * \brief This function prepares the MAC to abort the execution of function
  *        OnRadioRxDone in case of a reception error.
  */
-static void PrepareRxDoneAbort( void );
+static void PrepareRxDoneAbort(void);
 
 /*!
  * \brief Function to be executed on Radio Rx Done event
  */
-static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
+static void OnRadioRxDone(uint8_t* payload, uint16_t size, int16_t rssi, int8_t snr);
 
 /*!
  * \brief Function executed on Radio Tx Timeout event
  */
-static void OnRadioTxTimeout( void );
+static void OnRadioTxTimeout(void);
 
 /*!
  * \brief Function executed on Radio Rx error event
  */
-static void OnRadioRxError( void );
+static void OnRadioRxError(void);
 
 /*!
  * \brief Function executed on Radio Rx Timeout event
  */
-static void OnRadioRxTimeout( void );
+static void OnRadioRxTimeout(void);
 
 /*!
  * \brief Function executed on Resend Frame timer event.
  */
-static void OnMacStateCheckTimerEvent( void );
+static void OnMacStateCheckTimerEvent(void);
 
 /*!
  * \brief Function executed on duty cycle delayed Tx  timer event
  */
-static void OnTxDelayedTimerEvent( void );
+static void OnTxDelayedTimerEvent(void);
 
 /*!
  * \brief Function executed on first Rx window timer event
  */
-static void OnRxWindow1TimerEvent( void );
+static void OnRxWindow1TimerEvent(void);
 
 /*!
  * \brief Function executed on second Rx window timer event
  */
-static void OnRxWindow2TimerEvent( void );
+static void OnRxWindow2TimerEvent(void);
 
 /*!
  * \brief Function executed on AckTimeout timer event
  */
-static void OnAckTimeoutTimerEvent( void );
+static void OnAckTimeoutTimerEvent(void);
 
 /*!
  * \brief Searches and set the next random available channel
@@ -716,14 +692,14 @@
  * \retval status  Function status [1: OK, 0: Unable to find a channel on the
  *                                  current datarate]
  */
-static bool SetNextChannel( TimerTime_t* time );
+static bool SetNextChannel(TimerTime_t* time);
 
 /*!
  * \brief Sets the network to public or private. Updates the sync byte.
  *
  * \param [IN] enable if true, it enables a public network
  */
-static void SetPublicNetwork( bool enable );
+static void SetPublicNetwork(bool enable);
 
 /*!
  * \brief Initializes and opens the reception window
@@ -733,7 +709,8 @@
  * \param [IN] bandwidth window channel bandwidth
  * \param [IN] timeout window channel timeout
  */
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
+static void RxWindowSetup(uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout,
+                          bool rxContinuous);
 
 /*!
  * \brief Verifies if the RX window 2 frequency is in range
@@ -742,8 +719,7 @@
  *
  * \retval status  Function status [1: OK, 0: Frequency not applicable]
  */
-static bool Rx2FreqInRange( uint32_t freq );
-
+static bool Rx2FreqInRange(uint32_t freq);
 
 /*!
  * \brief Adds a new MAC command to be sent.
@@ -762,7 +738,7 @@
  *
  * \retval status  Function status [0: OK, 1: Unknown command, 2: Buffer full]
  */
-static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );
+static LoRaMacStatus_t AddMacCommand(uint8_t cmd, uint8_t p1, uint8_t p2);
 
 /*!
  * \brief Parses the MAC commands which must be repeated.
@@ -776,7 +752,7 @@
  *
  * \retval Size of the MAC commands to repeat.
  */
-static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut );
+static uint8_t ParseMacCommandsToRepeat(uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut);
 
 /*!
  * \brief Validates if the payload fits into the frame, taking the datarate
@@ -794,7 +770,7 @@
  * \retval [false: payload does not fit into the frame, true: payload fits into
  *          the frame]
  */
-static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
+static bool ValidatePayloadLength(uint8_t lenN, int8_t datarate, uint8_t fOptsLen);
 
 /*!
  * \brief Counts the number of bits in a mask.
@@ -804,9 +780,9 @@
  *
  * \retval Number of enabled bits in the mask.
  */
-static uint8_t CountBits( uint16_t mask, uint8_t nbBits );
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
+static uint8_t CountBits(uint16_t mask, uint8_t nbBits);
+
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
 /*!
  * \brief Counts the number of enabled 125 kHz channels in the channel mask.
  *        This function can only be applied to US915 band.
@@ -815,16 +791,16 @@
  *
  * \retval Number of enabled channels in the channel mask
  */
-static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask );
-
-#if defined( USE_BAND_915_HYBRID )
+static uint8_t CountNbEnabled125kHzChannels(uint16_t* channelsMask);
+
+#if defined(USE_BAND_915_HYBRID)
 /*!
  * \brief Validates the correctness of the channel mask for US915, hybrid mode.
  *
  * \param [IN] mask Block definition to set.
  * \param [OUT] channelsMask Pointer to the first element of the channel mask
  */
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask );
+static void ReenableChannels(uint16_t mask, uint16_t* channelMask);
 
 /*!
  * \brief Validates the correctness of the channel mask for US915, hybrid mode.
@@ -833,7 +809,7 @@
  *
  * \retval [true: channel mask correct, false: channel mask not correct]
  */
-static bool ValidateChannelMask( uint16_t* channelMask );
+static bool ValidateChannelMask(uint16_t* channelMask);
 #endif
 
 #endif
@@ -843,7 +819,7 @@
  *
  * \retval Returns the maximum valid tx power
  */
-static int8_t LimitTxPower( int8_t txPower );
+static int8_t LimitTxPower(int8_t txPower);
 
 /*!
  * \brief Verifies, if a value is in a given range.
@@ -856,7 +832,7 @@
  *
  * \retval Returns the maximum valid tx power
  */
-static bool ValueInRange( int8_t value, int8_t min, int8_t max );
+static bool ValueInRange(int8_t value, int8_t min, int8_t max);
 
 /*!
  * \brief Calculates the next datarate to set, when ADR is on or off
@@ -871,7 +847,7 @@
  *
  * \retval Returns the state of ADR ack request
  */
-static bool AdrNextDr( bool adrEnabled, bool isTx, int8_t* datarateOut, int8_t* txpowerOut );
+static bool AdrNextDr(bool adrEnabled, bool isTx, int8_t* datarateOut, int8_t* txpowerOut);
 
 /*!
  * \brief Disables channel in a specified channel mask
@@ -882,12 +858,13 @@
  *
  * \retval [true, if disable was successful, false if not]
  */
-static bool DisableChannelInMask( uint8_t id, uint16_t* mask );
+static bool DisableChannelInMask(uint8_t id, uint16_t* mask);
 
 /*!
  * \brief Decodes MAC commands in the fOpts field and in the payload
  */
-static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr );
+static void ProcessMacCommands(uint8_t* payload, uint8_t macIndex, uint8_t commandsSize,
+                               uint8_t snr);
 
 /*!
  * \brief LoRaMAC layer generic send frame
@@ -898,7 +875,7 @@
  * \param [IN] fBufferSize MAC data buffer size
  * \retval status          Status of the operation.
  */
-LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
+LoRaMacStatus_t Send(LoRaMacHeader_t* macHdr, uint8_t fPort, void* fBuffer, uint16_t fBufferSize);
 
 /*!
  * \brief LoRaMAC layer frame buffer initialization
@@ -911,24 +888,26 @@
  * \param [IN] fBufferSize MAC data buffer size
  * \retval status          Status of the operation.
  */
-LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
+LoRaMacStatus_t PrepareFrame(LoRaMacHeader_t* macHdr, LoRaMacFrameCtrl_t* fCtrl, uint8_t fPort,
+                             void* fBuffer, uint16_t fBufferSize);
 
 /*
  * \brief Schedules the frame according to the duty cycle
  *
  * \retval Status of the operation
  */
-static LoRaMacStatus_t ScheduleTx( void );
+static LoRaMacStatus_t ScheduleTx(void);
 
 /*
  * \brief Calculates the back-off time for the band of a channel.
  *
  * \param [IN] channel     The last Tx channel index
  */
-static void CalculateBackOff( uint8_t channel );
+static void CalculateBackOff(uint8_t channel);
 
 /*!
- * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
+ * \brief LoRaMAC layer prepared frame buffer transmission with channel
+ * specification
  *
  * \remark PrepareFrame must be called at least once before calling this
  *         function.
@@ -936,3124 +915,2673 @@
  * \param [IN] channel     Channel parameters
  * \retval status          Status of the operation.
  */
-LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
-
-
-
-static void OnRadioTxDone( void )
-{
-    TimerTime_t curTime = TimerGetCurrentTime( );
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
-    }
-    else
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    // Store last Tx channel
-    LastTxChannel = Channel;
-    // Update last tx done time for the current channel
-    Bands[Channels[LastTxChannel].Band].LastTxDoneTime = curTime;
-    // Update Aggregated last tx done time
-    AggregatedLastTxDoneTime = curTime;
-
-    // Update join tx done and time on air 
-    if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
-    {
-        JoinAggTimeOnAir += TxTimeOnAir;
-        LastJoinTxTime    = curTime;
-    }
-
-    if( IsRxWindowsEnabled == true )
-    {
-        TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
-        TimerStart( &RxWindowTimer1 );
-        if( LoRaMacDeviceClass != CLASS_C )
-        {
-            TimerSetValue( &RxWindowTimer2, RxWindow2Delay );
-            TimerStart( &RxWindowTimer2 );
-        }
-        if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested == true ) )
-        {
-            TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + ACK_TIMEOUT +
-                                             randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) );
-            TimerStart( &AckTimeoutTimer );
-        }
-    }
-    else
-    {
-        McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
-
-        if( LoRaMacFlags.Value == 0 )
-        {
-            LoRaMacFlags.Bits.McpsReq = 1;
-        }
-        LoRaMacFlags.Bits.MacDone = 1;
-    }
-
-    if( NodeAckRequested == false )
-    {
-        McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-        ChannelsNbRepCounter++;
-    }
-}
-
-static void PrepareRxDoneAbort( void )
-{
-    LoRaMacState |= MAC_RX_ABORT;
-
-    if( NodeAckRequested )
-    {
-        OnAckTimeoutTimerEvent( );
-    }
-
-    if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    LoRaMacFlags.Bits.McpsInd = 1;
-    LoRaMacFlags.Bits.MacDone = 1;
-
-    // Trig OnMacCheckTimerEvent call as soon as possible
-    TimerSetValue( &MacStateCheckTimer, 1000 );
-    TimerStart( &MacStateCheckTimer );
-}
-
-static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
-{
-    LoRaMacHeader_t macHdr;
-    LoRaMacFrameCtrl_t fCtrl;
-    bool skipIndication = false;
-
-    uint8_t pktHeaderLen = 0;
-    uint32_t address = 0;
-    uint8_t appPayloadStartIndex = 0;
-    uint8_t port = 0xFF;
-    uint8_t frameLen = 0;
-    uint32_t mic = 0;
-    uint32_t micRx = 0;
-
-    uint16_t sequenceCounter = 0;
-    uint16_t sequenceCounterPrev = 0;
-    uint16_t sequenceCounterDiff = 0;
-    uint32_t downLinkCounter = 0;
-
-    MulticastParams_t *curMulticastParams = NULL;
-    uint8_t *nwkSKey = LoRaMacNwkSKey;
-    uint8_t *appSKey = LoRaMacAppSKey;
-
-    uint8_t multicast = 0;
-
-    bool isMicOk = false;
-
-    McpsConfirm.AckReceived = false;
-    McpsIndication.Rssi = rssi;
-    McpsIndication.Snr = snr;
-    McpsIndication.RxSlot = RxSlot;
-    McpsIndication.Port = 0;
-    McpsIndication.Multicast = 0;
-    McpsIndication.FramePending = 0;
-    McpsIndication.Buffer = NULL;
-    McpsIndication.BufferSize = 0;
-    McpsIndication.RxData = false;
-    McpsIndication.AckReceived = false;
-    McpsIndication.DownLinkCounter = 0;
-    McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
-
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
+LoRaMacStatus_t SendFrameOnChannel(ChannelParams_t channel);
+
+static void OnRadioTxDone(void) {
+  TimerTime_t curTime = TimerGetCurrentTime();
+  if (LoRaMacDeviceClass != CLASS_C) {
+    Radio.Sleep();
+  }
+  else {
+    OnRxWindow2TimerEvent();
+  }
+
+  // Store last Tx channel
+  LastTxChannel = Channel;
+  // Update last tx done time for the current channel
+  Bands[Channels[LastTxChannel].Band].LastTxDoneTime = curTime;
+  // Update Aggregated last tx done time
+  AggregatedLastTxDoneTime = curTime;
+
+  // Update join tx done and time on air
+  if ((LoRaMacFlags.Bits.MlmeReq == 1) && (MlmeConfirm.MlmeRequest == MLME_JOIN)) {
+    JoinAggTimeOnAir += TxTimeOnAir;
+    LastJoinTxTime = curTime;
+  }
+
+  if (IsRxWindowsEnabled == true) {
+    TimerSetValue(&RxWindowTimer1, RxWindow1Delay);
+    TimerStart(&RxWindowTimer1);
+    if (LoRaMacDeviceClass != CLASS_C) {
+      TimerSetValue(&RxWindowTimer2, RxWindow2Delay);
+      TimerStart(&RxWindowTimer2);
     }
-    TimerStop( &RxWindowTimer2 );
-
-    macHdr.Value = payload[pktHeaderLen++];
-
-    switch( macHdr.Bits.MType )
-    {
-        case FRAME_TYPE_JOIN_ACCEPT:
-            if( IsLoRaMacNetworkJoined == true )
-            {
-                break;
-            }
-            LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
-
-            LoRaMacRxPayload[0] = macHdr.Value;
-
-            LoRaMacJoinComputeMic( LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic );
-
-            micRx |= ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
-            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8 );
-            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
-            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );
-
-            if( micRx == mic )
-            {
-                LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
-
-                LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
-                LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
-                LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
-
-                LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
-                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
-                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
-                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
-
-                // DLSettings
-                Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
-                Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
-                // RxDelay
-                ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
-                if( ReceiveDelay1 == 0 )
-                {
-                    ReceiveDelay1 = 1;
-                }
-                ReceiveDelay1 *= 1e6;
-                ReceiveDelay2 = ReceiveDelay1 + 1e6;
-
-#if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-                //CFList
-                if( ( size - 1 ) > 16 )
-                {
-                    ChannelParams_t param;
-                    param.DrRange.Value = ( DR_5 << 4 ) | DR_0;
-
-                    LoRaMacState |= MAC_TX_CONFIG;
-                    for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 )
-                    {
-                        param.Frequency = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100;
-                        LoRaMacChannelAdd( i, param );
-                    }
-                    LoRaMacState &= ~MAC_TX_CONFIG;
-                }
-#endif
-                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                IsLoRaMacNetworkJoined = true;
-               
-                // Do not change the datarate
-                // ChannelsDatarate = ChannelsDefaultDatarate;
-            }
-            else
-            {
-                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
-            }
-            break;
-        case FRAME_TYPE_DATA_CONFIRMED_DOWN:
-        case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
-            {
-                address = payload[pktHeaderLen++];
-                address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
-                address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
-                address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );
-
-                if( address != LoRaMacDevAddr )
-                {
-                    curMulticastParams = MulticastChannels;
-                    while( curMulticastParams != NULL )
-                    {
-                        if( address == curMulticastParams->Address )
-                        {
-                            multicast = 1;
-                            nwkSKey = curMulticastParams->NwkSKey;
-                            appSKey = curMulticastParams->AppSKey;
-                            downLinkCounter = curMulticastParams->DownLinkCounter;
-                            break;
-                        }
-                        curMulticastParams = curMulticastParams->Next;
-                    }
-                    if( multicast == 0 )
-                    {
-                        // We are not the destination of this frame.
-                        McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
-                        PrepareRxDoneAbort( );
-                        return;
-                    }
-                }
-                else
-                {
-                    multicast = 0;
-                    nwkSKey = LoRaMacNwkSKey;
-                    appSKey = LoRaMacAppSKey;
-                    downLinkCounter = DownLinkCounter;
-                }
-
-                fCtrl.Value = payload[pktHeaderLen++];
-
-                sequenceCounter = ( uint16_t )payload[pktHeaderLen++];
-                sequenceCounter |= ( uint16_t )payload[pktHeaderLen++] << 8;
-
-                appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;
-
-                micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
-                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 1] << 8 );
-                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 2] << 16 );
-                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 3] << 24 );
-
-                sequenceCounterPrev = ( uint16_t )downLinkCounter;
-                sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev );
-
-                if( sequenceCounterDiff < ( 1 << 15 ) )
-                {
-                    downLinkCounter += sequenceCounterDiff;
-                    LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
-                    if( micRx == mic )
-                    {
-                        isMicOk = true;
-                    }
-                }
-                else
-                {
-                    // check for sequence roll-over
-                    uint32_t  downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff;
-                    LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic );
-                    if( micRx == mic )
-                    {
-                        isMicOk = true;
-                        downLinkCounter = downLinkCounterTmp;
-                    }
-                }
-
-                // Check for a the maximum allowed counter difference
-                if( sequenceCounterDiff >= MAX_FCNT_GAP )
-                {
-                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
-                    McpsIndication.DownLinkCounter = downLinkCounter;
-                    PrepareRxDoneAbort( );
-                    return;
-                }
-
-                if( isMicOk == true )
-                {
-                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                    McpsIndication.Multicast = multicast;
-                    McpsIndication.FramePending = fCtrl.Bits.FPending;
-                    McpsIndication.Buffer = NULL;
-                    McpsIndication.BufferSize = 0;
-                    McpsIndication.DownLinkCounter = downLinkCounter;
-
-                    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-
-                    MacCommandsBufferToRepeatIndex = 0;
-
-                    // Update 32 bits downlink counter
-                    if( multicast == 1 )
-                    {
-                        McpsIndication.McpsIndication = MCPS_MULTICAST;
-
-                        if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) &&
-                            ( curMulticastParams->DownLinkCounter != 0 ) )
-                        {
-                            McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
-                            McpsIndication.DownLinkCounter = downLinkCounter;
-                            PrepareRxDoneAbort( );
-                            return;
-                        }
-                        curMulticastParams->DownLinkCounter = downLinkCounter;
-                    }
-                    else
-                    {
-                        if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
-                        {
-                            SrvAckRequested = true;
-                            McpsIndication.McpsIndication = MCPS_CONFIRMED;
-
-                            if( ( DownLinkCounter == downLinkCounter ) &&
-                                ( DownLinkCounter != 0 ) )
-                            {
-                                // Duplicated confirmed downlink. Skip indication.
-                                skipIndication = true;
-                            }
-                        }
-                        else
-                        {
-                            SrvAckRequested = false;
-                            McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
-
-                            if( ( DownLinkCounter == downLinkCounter ) &&
-                                ( DownLinkCounter != 0 ) )
-                            {
-                                McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
-                                McpsIndication.DownLinkCounter = downLinkCounter;
-                                PrepareRxDoneAbort( );
-                                return;
-                            }
-                        }
-                        DownLinkCounter = downLinkCounter;
-                    }
-                    
-                    if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
-                    {
-                        port = payload[appPayloadStartIndex++];
-                        frameLen = ( size - 4 ) - appPayloadStartIndex;
-
-                        McpsIndication.Port = port;
-
-                        if( port == 0 )
-                        {
-                            if( fCtrl.Bits.FOptsLen == 0 )
-                            {
-                                LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
-                                                       frameLen,
-                                                       nwkSKey,
-                                                       address,
-                                                       DOWN_LINK,
-                                                       downLinkCounter,
-                                                       LoRaMacRxPayload );
-
-                                // Decode frame payload MAC commands
-                                ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
-                            }
-                            else
-                            {
-                                skipIndication = true;
-                            }
-                        }
-                        else
-                        {
-                            if( fCtrl.Bits.FOptsLen > 0 )
-                            {
-                                // Decode Options field MAC commands. Omit the fPort.
-                                ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr );
-                            }
-
-                            LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
-                                                   frameLen,
-                                                   appSKey,
-                                                   address,
-                                                   DOWN_LINK,
-                                                   downLinkCounter,
-                                                   LoRaMacRxPayload );
-
-                            if( skipIndication == false )
-                            {
-                                McpsIndication.Buffer = LoRaMacRxPayload;
-                                McpsIndication.BufferSize = frameLen;
-                                McpsIndication.RxData = true;
-                            }
-                        }
-                    }
-                    else
-                    {
-                        if( fCtrl.Bits.FOptsLen > 0 )
-                        {
-                            // Decode Options field MAC commands
-                            ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
-                        }
-                    }
-
-                    if( skipIndication == false )
-                    {
-                         // Check if the frame is an acknowledgement
-                         if( fCtrl.Bits.Ack == 1 )
-                         {
-                         	McpsConfirm.AckReceived = true;
-                         	McpsIndication.AckReceived = true;
-                         	
-                         	// Stop the AckTimeout timer as no more retransmissions
-                         	// are needed.
-                         	TimerStop( &AckTimeoutTimer );
-                         }
-                         else
-                         {
-                         	McpsConfirm.AckReceived = false;
-                         	
-                         	if( AckTimeoutRetriesCounter > AckTimeoutRetries )
-                         	{
-                         		// Stop the AckTimeout timer as no more retransmissions
-                         		// are needed.
-                         		TimerStop( &AckTimeoutTimer );
-                         	}
-                        }
-                        LoRaMacFlags.Bits.McpsInd = 1;
-                    }
-                }
-                else
-                {
-                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
-
-                    PrepareRxDoneAbort( );
-                    return;
-                }
-            }
-            break;
-        case FRAME_TYPE_PROPRIETARY:
-            {
-                memcpy1( LoRaMacRxPayload, &payload[pktHeaderLen], size );
-
-                McpsIndication.McpsIndication = MCPS_PROPRIETARY;
-                McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                McpsIndication.Buffer = LoRaMacRxPayload;
-                McpsIndication.BufferSize = size - pktHeaderLen;
-
-                LoRaMacFlags.Bits.McpsInd = 1;
-                break;
-            }
-        default:
-            McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-            PrepareRxDoneAbort( );
-            break;
+    if ((LoRaMacDeviceClass == CLASS_C) || (NodeAckRequested == true)) {
+      TimerSetValue(&AckTimeoutTimer,
+                    RxWindow2Delay + ACK_TIMEOUT + randr(-ACK_TIMEOUT_RND, ACK_TIMEOUT_RND));
+      TimerStart(&AckTimeoutTimer);
     }
-
-    if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
-    {
-        OnRxWindow2TimerEvent( );
+  }
+  else {
+    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+    MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+
+    if (LoRaMacFlags.Value == 0) {
+      LoRaMacFlags.Bits.McpsReq = 1;
     }
     LoRaMacFlags.Bits.MacDone = 1;
-
-    // Trig OnMacCheckTimerEvent call as soon as possible
-    TimerSetValue( &MacStateCheckTimer, 1000 );
-    TimerStart( &MacStateCheckTimer );
+  }
+
+  if (NodeAckRequested == false) {
+    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+    ChannelsNbRepCounter++;
+  }
+}
+
+static void PrepareRxDoneAbort(void) {
+  LoRaMacState |= MAC_RX_ABORT;
+
+  if (NodeAckRequested) {
+    OnAckTimeoutTimerEvent();
+  }
+
+  if ((RxSlot == 0) && (LoRaMacDeviceClass == CLASS_C)) {
+    OnRxWindow2TimerEvent();
+  }
+
+  LoRaMacFlags.Bits.McpsInd = 1;
+  LoRaMacFlags.Bits.MacDone = 1;
+
+  // Trig OnMacCheckTimerEvent call as soon as possible
+  TimerSetValue(&MacStateCheckTimer, 1000);
+  TimerStart(&MacStateCheckTimer);
 }
 
-static void OnRadioTxTimeout( void )
-{
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
+static void OnRadioRxDone(uint8_t* payload, uint16_t size, int16_t rssi, int8_t snr) {
+  LoRaMacHeader_t    macHdr;
+  LoRaMacFrameCtrl_t fCtrl;
+  bool               skipIndication = false;
+
+  uint8_t  pktHeaderLen         = 0;
+  uint32_t address              = 0;
+  uint8_t  appPayloadStartIndex = 0;
+  uint8_t  port                 = 0xFF;
+  uint8_t  frameLen             = 0;
+  uint32_t mic                  = 0;
+  uint32_t micRx                = 0;
+
+  uint16_t sequenceCounter     = 0;
+  uint16_t sequenceCounterPrev = 0;
+  uint16_t sequenceCounterDiff = 0;
+  uint32_t downLinkCounter     = 0;
+
+  MulticastParams_t* curMulticastParams = NULL;
+  uint8_t*           nwkSKey            = LoRaMacNwkSKey;
+  uint8_t*           appSKey            = LoRaMacAppSKey;
+
+  uint8_t multicast = 0;
+
+  bool isMicOk = false;
+
+  McpsConfirm.AckReceived        = false;
+  McpsIndication.Rssi            = rssi;
+  McpsIndication.Snr             = snr;
+  McpsIndication.RxSlot          = RxSlot;
+  McpsIndication.Port            = 0;
+  McpsIndication.Multicast       = 0;
+  McpsIndication.FramePending    = 0;
+  McpsIndication.Buffer          = NULL;
+  McpsIndication.BufferSize      = 0;
+  McpsIndication.RxData          = false;
+  McpsIndication.AckReceived     = false;
+  McpsIndication.DownLinkCounter = 0;
+  McpsIndication.McpsIndication  = MCPS_UNCONFIRMED;
+
+  if (LoRaMacDeviceClass != CLASS_C) {
+    Radio.Sleep();
+  }
+  TimerStop(&RxWindowTimer2);
+
+  macHdr.Value = payload[pktHeaderLen++];
+
+  switch (macHdr.Bits.MType) {
+    case FRAME_TYPE_JOIN_ACCEPT:
+      if (IsLoRaMacNetworkJoined == true) {
+        break;
+      }
+      LoRaMacJoinDecrypt(payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1);
+
+      LoRaMacRxPayload[0] = macHdr.Value;
+
+      LoRaMacJoinComputeMic(LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic);
+
+      micRx |= (uint32_t)LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
+      micRx |= ((uint32_t)LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8);
+      micRx |= ((uint32_t)LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16);
+      micRx |= ((uint32_t)LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24);
+
+      if (micRx == mic) {
+        LoRaMacJoinComputeSKeys(LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce,
+                                LoRaMacNwkSKey, LoRaMacAppSKey);
+
+        LoRaMacNetID = (uint32_t)LoRaMacRxPayload[4];
+        LoRaMacNetID |= ((uint32_t)LoRaMacRxPayload[5] << 8);
+        LoRaMacNetID |= ((uint32_t)LoRaMacRxPayload[6] << 16);
+
+        LoRaMacDevAddr = (uint32_t)LoRaMacRxPayload[7];
+        LoRaMacDevAddr |= ((uint32_t)LoRaMacRxPayload[8] << 8);
+        LoRaMacDevAddr |= ((uint32_t)LoRaMacRxPayload[9] << 16);
+        LoRaMacDevAddr |= ((uint32_t)LoRaMacRxPayload[10] << 24);
+
+        // DLSettings
+        Rx1DrOffset         = (LoRaMacRxPayload[11] >> 4) & 0x07;
+        Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
+        // RxDelay
+        ReceiveDelay1 = (LoRaMacRxPayload[12] & 0x0F);
+        if (ReceiveDelay1 == 0) {
+          ReceiveDelay1 = 1;
+        }
+        ReceiveDelay1 *= 1e6;
+        ReceiveDelay2 = ReceiveDelay1 + 1e6;
+
+#if !(defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+        // CFList
+        if ((size - 1) > 16) {
+          ChannelParams_t param;
+          param.DrRange.Value = (DR_5 << 4) | DR_0;
+
+          LoRaMacState |= MAC_TX_CONFIG;
+          for (uint8_t i = 3, j = 0; i < (5 + 3); i++, j += 3) {
+            param.Frequency =
+              ((uint32_t)LoRaMacRxPayload[13 + j] | ((uint32_t)LoRaMacRxPayload[14 + j] << 8) |
+               ((uint32_t)LoRaMacRxPayload[15 + j] << 16)) *
+              100;
+            LoRaMacChannelAdd(i, param);
+          }
+          LoRaMacState &= ~MAC_TX_CONFIG;
+        }
+#endif
+        MlmeConfirm.Status     = LORAMAC_EVENT_INFO_STATUS_OK;
+        IsLoRaMacNetworkJoined = true;
+
+        // Do not change the datarate
+        // ChannelsDatarate = ChannelsDefaultDatarate;
+      }
+      else {
+        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
+      }
+      break;
+    case FRAME_TYPE_DATA_CONFIRMED_DOWN:
+    case FRAME_TYPE_DATA_UNCONFIRMED_DOWN: {
+      address = payload[pktHeaderLen++];
+      address |= ((uint32_t)payload[pktHeaderLen++] << 8);
+      address |= ((uint32_t)payload[pktHeaderLen++] << 16);
+      address |= ((uint32_t)payload[pktHeaderLen++] << 24);
+
+      if (address != LoRaMacDevAddr) {
+        curMulticastParams = MulticastChannels;
+        while (curMulticastParams != NULL) {
+          if (address == curMulticastParams->Address) {
+            multicast       = 1;
+            nwkSKey         = curMulticastParams->NwkSKey;
+            appSKey         = curMulticastParams->AppSKey;
+            downLinkCounter = curMulticastParams->DownLinkCounter;
+            break;
+          }
+          curMulticastParams = curMulticastParams->Next;
+        }
+        if (multicast == 0) {
+          // We are not the destination of this frame.
+          McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
+          PrepareRxDoneAbort();
+          return;
+        }
+      }
+      else {
+        multicast       = 0;
+        nwkSKey         = LoRaMacNwkSKey;
+        appSKey         = LoRaMacAppSKey;
+        downLinkCounter = DownLinkCounter;
+      }
+
+      fCtrl.Value = payload[pktHeaderLen++];
+
+      sequenceCounter = (uint16_t)payload[pktHeaderLen++];
+      sequenceCounter |= (uint16_t)payload[pktHeaderLen++] << 8;
+
+      appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;
+
+      micRx |= (uint32_t)payload[size - LORAMAC_MFR_LEN];
+      micRx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 1] << 8);
+      micRx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 2] << 16);
+      micRx |= ((uint32_t)payload[size - LORAMAC_MFR_LEN + 3] << 24);
+
+      sequenceCounterPrev = (uint16_t)downLinkCounter;
+      sequenceCounterDiff = (sequenceCounter - sequenceCounterPrev);
+
+      if (sequenceCounterDiff < (1 << 15)) {
+        downLinkCounter += sequenceCounterDiff;
+        LoRaMacComputeMic(payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK,
+                          downLinkCounter, &mic);
+        if (micRx == mic) {
+          isMicOk = true;
+        }
+      }
+      else {
+        // check for sequence roll-over
+        uint32_t downLinkCounterTmp = downLinkCounter + 0x10000 + (int16_t)sequenceCounterDiff;
+        LoRaMacComputeMic(payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK,
+                          downLinkCounterTmp, &mic);
+        if (micRx == mic) {
+          isMicOk         = true;
+          downLinkCounter = downLinkCounterTmp;
+        }
+      }
+
+      // Check for a the maximum allowed counter difference
+      if (sequenceCounterDiff >= MAX_FCNT_GAP) {
+        McpsIndication.Status          = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
+        McpsIndication.DownLinkCounter = downLinkCounter;
+        PrepareRxDoneAbort();
+        return;
+      }
+
+      if (isMicOk == true) {
+        McpsIndication.Status          = LORAMAC_EVENT_INFO_STATUS_OK;
+        McpsIndication.Multicast       = multicast;
+        McpsIndication.FramePending    = fCtrl.Bits.FPending;
+        McpsIndication.Buffer          = NULL;
+        McpsIndication.BufferSize      = 0;
+        McpsIndication.DownLinkCounter = downLinkCounter;
+
+        McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
+
+        MacCommandsBufferToRepeatIndex = 0;
+
+        // Update 32 bits downlink counter
+        if (multicast == 1) {
+          McpsIndication.McpsIndication = MCPS_MULTICAST;
+
+          if ((curMulticastParams->DownLinkCounter == downLinkCounter) &&
+              (curMulticastParams->DownLinkCounter != 0)) {
+            McpsIndication.Status          = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
+            McpsIndication.DownLinkCounter = downLinkCounter;
+            PrepareRxDoneAbort();
+            return;
+          }
+          curMulticastParams->DownLinkCounter = downLinkCounter;
+        }
+        else {
+          if (macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN) {
+            SrvAckRequested               = true;
+            McpsIndication.McpsIndication = MCPS_CONFIRMED;
+
+            if ((DownLinkCounter == downLinkCounter) && (DownLinkCounter != 0)) {
+              // Duplicated confirmed downlink. Skip indication.
+              skipIndication = true;
+            }
+          }
+          else {
+            SrvAckRequested               = false;
+            McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
+
+            if ((DownLinkCounter == downLinkCounter) && (DownLinkCounter != 0)) {
+              McpsIndication.Status          = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
+              McpsIndication.DownLinkCounter = downLinkCounter;
+              PrepareRxDoneAbort();
+              return;
+            }
+          }
+          DownLinkCounter = downLinkCounter;
+        }
+
+        if (((size - 4) - appPayloadStartIndex) > 0) {
+          port     = payload[appPayloadStartIndex++];
+          frameLen = (size - 4) - appPayloadStartIndex;
+
+          McpsIndication.Port = port;
+
+          if (port == 0) {
+            if (fCtrl.Bits.FOptsLen == 0) {
+              LoRaMacPayloadDecrypt(payload + appPayloadStartIndex, frameLen, nwkSKey, address,
+                                    DOWN_LINK, downLinkCounter, LoRaMacRxPayload);
+
+              // Decode frame payload MAC commands
+              ProcessMacCommands(LoRaMacRxPayload, 0, frameLen, snr);
+            }
+            else {
+              skipIndication = true;
+            }
+          }
+          else {
+            if (fCtrl.Bits.FOptsLen > 0) {
+              // Decode Options field MAC commands. Omit the fPort.
+              ProcessMacCommands(payload, 8, appPayloadStartIndex - 1, snr);
+            }
+
+            LoRaMacPayloadDecrypt(payload + appPayloadStartIndex, frameLen, appSKey, address,
+                                  DOWN_LINK, downLinkCounter, LoRaMacRxPayload);
+
+            if (skipIndication == false) {
+              McpsIndication.Buffer     = LoRaMacRxPayload;
+              McpsIndication.BufferSize = frameLen;
+              McpsIndication.RxData     = true;
+            }
+          }
+        }
+        else {
+          if (fCtrl.Bits.FOptsLen > 0) {
+            // Decode Options field MAC commands
+            ProcessMacCommands(payload, 8, appPayloadStartIndex, snr);
+          }
+        }
+
+        if (skipIndication == false) {
+          // Check if the frame is an acknowledgement
+          if (fCtrl.Bits.Ack == 1) {
+            McpsConfirm.AckReceived    = true;
+            McpsIndication.AckReceived = true;
+
+            // Stop the AckTimeout timer as no more retransmissions
+            // are needed.
+            TimerStop(&AckTimeoutTimer);
+          }
+          else {
+            McpsConfirm.AckReceived = false;
+
+            if (AckTimeoutRetriesCounter > AckTimeoutRetries) {
+              // Stop the AckTimeout timer as no more retransmissions
+              // are needed.
+              TimerStop(&AckTimeoutTimer);
+            }
+          }
+          LoRaMacFlags.Bits.McpsInd = 1;
+        }
+      }
+      else {
+        McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
+
+        PrepareRxDoneAbort();
+        return;
+      }
+    } break;
+    case FRAME_TYPE_PROPRIETARY: {
+      memcpy1(LoRaMacRxPayload, &payload[pktHeaderLen], size);
+
+      McpsIndication.McpsIndication = MCPS_PROPRIETARY;
+      McpsIndication.Status         = LORAMAC_EVENT_INFO_STATUS_OK;
+      McpsIndication.Buffer         = LoRaMacRxPayload;
+      McpsIndication.BufferSize     = size - pktHeaderLen;
+
+      LoRaMacFlags.Bits.McpsInd = 1;
+      break;
     }
-    else
-    {
-        OnRxWindow2TimerEvent( );
+    default:
+      McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+      PrepareRxDoneAbort();
+      break;
+  }
+
+  if ((RxSlot == 0) && (LoRaMacDeviceClass == CLASS_C)) {
+    OnRxWindow2TimerEvent();
+  }
+  LoRaMacFlags.Bits.MacDone = 1;
+
+  // Trig OnMacCheckTimerEvent call as soon as possible
+  TimerSetValue(&MacStateCheckTimer, 1000);
+  TimerStart(&MacStateCheckTimer);
+}
+
+static void OnRadioTxTimeout(void) {
+  if (LoRaMacDeviceClass != CLASS_C) {
+    Radio.Sleep();
+  }
+  else {
+    OnRxWindow2TimerEvent();
+  }
+
+  McpsConfirm.Status        = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
+  MlmeConfirm.Status        = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
+  LoRaMacFlags.Bits.MacDone = 1;
+}
+
+static void OnRadioRxError(void) {
+  if (LoRaMacDeviceClass != CLASS_C) {
+    Radio.Sleep();
+  }
+  else {
+    OnRxWindow2TimerEvent();
+  }
+
+  if (RxSlot == 1) {
+    if (NodeAckRequested == true) {
+      McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
     }
-
-    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
-    MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
+    MlmeConfirm.Status        = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
     LoRaMacFlags.Bits.MacDone = 1;
+  }
+}
+
+static void OnRadioRxTimeout(void) {
+  if (LoRaMacDeviceClass != CLASS_C) {
+    Radio.Sleep();
+  }
+  else {
+    OnRxWindow2TimerEvent();
+  }
+
+  if (RxSlot == 1) {
+    if (NodeAckRequested == true) {
+      McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+    }
+    MlmeConfirm.Status        = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
+    LoRaMacFlags.Bits.MacDone = 1;
+  }
 }
 
-static void OnRadioRxError( void )
-{
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
+static void OnMacStateCheckTimerEvent(void) {
+  TimerStop(&MacStateCheckTimer);
+  bool txTimeout = false;
+  bool txDone    = false;
+
+  if (LoRaMacFlags.Bits.MacDone == 1) {
+    if ((LoRaMacState & MAC_RX_ABORT) == MAC_RX_ABORT) {
+      LoRaMacState &= ~MAC_RX_ABORT;
+      LoRaMacState &= ~MAC_TX_RUNNING;
+    }
+
+    if ((LoRaMacFlags.Bits.MlmeReq == 1) || ((LoRaMacFlags.Bits.McpsReq == 1))) {
+      if ((McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT) ||
+          (MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT)) {
+        // Stop transmit cycle due to tx timeout.
+        LoRaMacState &= ~MAC_TX_RUNNING;
+        McpsConfirm.NbRetries   = AckTimeoutRetriesCounter;
+        McpsConfirm.AckReceived = false;
+        McpsConfirm.TxTimeOnAir = 0;
+        txTimeout               = true;
+      }
+    }
+
+    if ((NodeAckRequested == false) && (txTimeout == false)) {
+      if (LoRaMacFlags.Bits.MlmeReq == 1) {
+        if (MlmeConfirm.MlmeRequest == MLME_JOIN) {
+          if (MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK) {
+            UpLinkCounter = 0;
+          }
+          // Join messages aren't repeated automatically
+          ChannelsNbRepCounter = ChannelsNbRep;
+        }
+      }
+      if ((LoRaMacFlags.Bits.MlmeReq == 1) || ((LoRaMacFlags.Bits.McpsReq == 1))) {
+        if ((ChannelsNbRepCounter >= ChannelsNbRep) || (LoRaMacFlags.Bits.McpsInd == 1)) {
+          ChannelsNbRepCounter = 0;
+
+          txDone = true;
+          LoRaMacState &= ~MAC_TX_RUNNING;
+        }
+        else {
+          LoRaMacFlags.Bits.MacDone = 0;
+          // Sends the same frame again
+          ScheduleTx();
+        }
+      }
+    }
+
+    if (LoRaMacFlags.Bits.McpsInd == 1) {
+      if ((McpsConfirm.AckReceived == true) || (AckTimeoutRetriesCounter > AckTimeoutRetries)) {
+        AckTimeoutRetry       = false;
+        NodeAckRequested      = false;
+        txDone                = true;
+        McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
+
+        LoRaMacState &= ~MAC_TX_RUNNING;
+      }
     }
-    else
-    {
-        OnRxWindow2TimerEvent( );
+
+    if ((AckTimeoutRetry == true) && ((LoRaMacState & MAC_TX_DELAYED) == 0)) {
+      AckTimeoutRetry = false;
+      if ((AckTimeoutRetriesCounter < AckTimeoutRetries) &&
+          (AckTimeoutRetriesCounter <= MAX_ACK_RETRIES)) {
+        AckTimeoutRetriesCounter++;
+
+        if ((AckTimeoutRetriesCounter % 2) == 1) {
+          ChannelsDatarate = MAX(ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE);
+          // Check if new datarate is valid for the Payload length
+          if (ValidatePayloadLength(LoRaMacBufferPktLen - 13, ChannelsDatarate, 0) == false) {
+            // If invalid payload length, then revert to previous datarate
+            ChannelsDatarate++;
+          }
+        }
+        LoRaMacFlags.Bits.MacDone = 0;
+        // Sends the same frame again
+        ScheduleTx();
+      }
+      else {
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+        // Re-enable default channels LC1, LC2, LC3
+        ChannelsMask[0] = ChannelsMask[0] | (LC(1) + LC(2) + LC(3));
+#elif !defined(USE_BAND_915) && !defined(USE_BAND_915_HYBRID)
+#error "Please define a frequency band in the compiler options."
+#endif
+        LoRaMacState &= ~MAC_TX_RUNNING;
+
+        NodeAckRequested        = false;
+        McpsConfirm.AckReceived = false;
+        McpsConfirm.NbRetries   = AckTimeoutRetriesCounter;
+        txDone                  = true;
+      }
+    }
+
+    // Update uplink counter
+    if ((txDone == true) && (IsUpLinkCounterFixed == false)) {
+      UpLinkCounter++;
+
+      // Reset AdrAckCounter if downlink received
+      if ((LoRaMacFlags.Bits.McpsInd == 1) || (UpLinkCounter == 1)) {
+        AdrAckCounter = 0;
+      }
+      else {
+        AdrAckCounter++;
+      }
+    }
+  }
+  // Handle reception for Class B and Class C
+  if ((LoRaMacState & MAC_RX) == MAC_RX) {
+    LoRaMacState &= ~MAC_RX;
+  }
+
+  if (LoRaMacState == MAC_IDLE) {
+    if (LoRaMacFlags.Bits.McpsReq == 1) {
+      LoRaMacPrimitives->MacMcpsConfirm(&McpsConfirm);
+      LoRaMacFlags.Bits.McpsReq = 0;
+    }
+
+    if (LoRaMacFlags.Bits.MlmeReq == 1) {
+      LoRaMacPrimitives->MacMlmeConfirm(&MlmeConfirm);
+      LoRaMacFlags.Bits.MlmeReq = 0;
     }
 
-    if( RxSlot == 1 )
-    {
-        if( NodeAckRequested == true )
-        {
-            McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
+    LoRaMacFlags.Bits.MacDone = 0;
+  }
+  else {
+    // Operation not finished restart timer
+    TimerSetValue(&MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT);
+    TimerStart(&MacStateCheckTimer);
+  }
+
+  if (LoRaMacFlags.Bits.McpsInd == 1) {
+    LoRaMacPrimitives->MacMcpsIndication(&McpsIndication);
+    LoRaMacFlags.Bits.McpsInd = 0;
+  }
+}
+
+static void OnTxDelayedTimerEvent(void) {
+  TimerStop(&TxDelayedTimer);
+  LoRaMacState &= ~MAC_TX_DELAYED;
+
+  ScheduleTx();
+}
+
+static void OnRxWindow1TimerEvent(void) {
+  uint16_t symbTimeout = 5;  // DR_2, DR_1, DR_0
+  int8_t   datarate    = 0;
+  uint32_t bandwidth   = 0;  // LoRa 125 kHz
+
+  TimerStop(&RxWindowTimer1);
+  RxSlot = 0;
+
+  if (LoRaMacDeviceClass == CLASS_C) {
+    Radio.Standby();
+  }
+
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+  datarate = ChannelsDatarate - Rx1DrOffset;
+  if (datarate < 0) {
+    datarate = DR_0;
+  }
+
+  // For higher datarates, we increase the number of symbols generating a Rx
+  // Timeout
+  if ((datarate == DR_3) || (datarate == DR_4)) {  // DR_4, DR_3
+    symbTimeout = 8;
+  }
+  else if (datarate == DR_5) {
+    symbTimeout = 10;
+  }
+  else if (datarate == DR_6) {  // LoRa 250 kHz
+    bandwidth   = 1;
+    symbTimeout = 14;
+  }
+  RxWindowSetup(Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false);
+#elif (defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+  datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset];
+  if (datarate < 0) {
+    datarate = DR_0;
+  }
+  // For higher datarates, we increase the number of symbols generating a Rx
+  // Timeout
+
+  symbTimeout = 10;
+  // For low SF, we increase the number of symbols generating a Rx Timeout
+  switch (datarate) {
+    case DR_0:
+    case DR_8:
+    case DR_9:
+    case DR_10:
+      symbTimeout += 5;
+      break;
+    case DR_1:
+    case DR_11:
+      symbTimeout += 8;
+      break;
+    case DR_2:
+    case DR_4:
+    case DR_12:
+      symbTimeout += 9;
+      break;
+    case DR_3:
+    case DR_13:
+      symbTimeout += 10;
+      break;
+    default:
+      symbTimeout += 5;
+      break;
+  }
+
+  if (datarate >= DR_4) {  // LoRa 500 kHz
+    bandwidth = 2;
+  }
+  RxWindowSetup(923.3e6 + (Channel % 8) * 600e3, datarate, bandwidth, symbTimeout, false);
+#else
+#error "Please define a frequency band in the compiler options."
+#endif
+}
+
+static void OnRxWindow2TimerEvent(void) {
+  uint16_t symbTimeout = 5;  // DR_2, DR_1, DR_0
+  uint32_t bandwidth   = 0;  // LoRa 125 kHz
+
+  TimerStop(&RxWindowTimer2);
+  RxSlot = 1;
+
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+  // For higher datarates, we increase the number of symbols generating a Rx
+  // Timeout
+  if ((Rx2Channel.Datarate == DR_3) || (Rx2Channel.Datarate == DR_4)) {  // DR_4, DR_3
+    symbTimeout = 8;
+  }
+  else if (Rx2Channel.Datarate == DR_5) {
+    symbTimeout = 10;
+  }
+  else if (Rx2Channel.Datarate == DR_6) {  // LoRa 250 kHz
+    bandwidth   = 1;
+    symbTimeout = 14;
+  }
+#elif (defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+  // For higher datarates, we increase the number of symbols generating a Rx
+  // Timeout
+  switch (Rx2Channel.Datarate) {
+    case DR_0:  // SF10 - BW125
+      symbTimeout = 5;
+      break;
+
+    case DR_1:   // SF9  - BW125
+    case DR_2:   // SF8  - BW125
+    case DR_8:   // SF12 - BW500
+    case DR_9:   // SF11 - BW500
+    case DR_10:  // SF10 - BW500
+      symbTimeout = 8;
+      break;
+
+    case DR_3:   // SF7  - BW125
+    case DR_11:  // SF9  - BW500
+      symbTimeout = 10;
+      break;
+
+    case DR_4:   // SF8  - BW500
+    case DR_12:  // SF8  - BW500
+      symbTimeout = 14;
+      break;
+
+    case DR_13:  // SF7  - BW500
+      symbTimeout = 16;
+      break;
+    default:
+      break;
+  }
+  if (Rx2Channel.Datarate >= DR_4) {  // LoRa 500 kHz
+    bandwidth = 2;
+  }
+#else
+#error "Please define a frequency band in the compiler options."
+#endif
+  if (LoRaMacDeviceClass != CLASS_C) {
+    RxWindowSetup(Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, false);
+  }
+  else {
+    RxWindowSetup(Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, true);
+  }
+}
+
+static void OnAckTimeoutTimerEvent(void) {
+  TimerStop(&AckTimeoutTimer);
+
+  if (NodeAckRequested == true) {
+    AckTimeoutRetry = true;
+    LoRaMacState &= ~MAC_ACK_REQ;
+  }
+  if (LoRaMacDeviceClass == CLASS_C) {
+    LoRaMacFlags.Bits.MacDone = 1;
+  }
+}
+
+#if defined(USE_BAND_915)
+uint8_t GetNextJoinChannel(uint8_t* enabledChannels, uint8_t nbEnabledChannels) {
+  int8_t  channel = -1;
+  uint8_t block;
+  uint8_t i;
+
+  // Use 125KHz channel
+  if (ChannelsDatarate < DR_4) {
+    block         = JoinBlock[NextJoinBlock];
+    NextJoinBlock = (NextJoinBlock + 1) % 8;
+
+    // If next block is greater than max block then randomly select the next
+    // block
+    if (block >= 8)
+      block = randr(0, 7);
+
+    // Start search for next join channel at the selected block
+    for (i = 0; (i < 8) && (channel == -1); i++) {
+      uint8_t curBlock = (block + i) % 8;
+      uint8_t chMask;
+
+      // Cycle through all blocks before using a previously used block
+      if (((JoinBlocksRemaining & (1 << curBlock)) != 0)) {
+        chMask = (ChannelsMaskRemaining[curBlock / 2] >> (curBlock & 1 ? 8 : 0)) & 0xff;
+        if (chMask != 0) {
+          channel = randr(0, 7);
+          for (uint8_t i = 0; (i < 8); i++) {
+            if ((chMask & (1 << channel)) != 0) {
+              uint16_t chMaskTmp = (1 << channel);
+              chMaskTmp          = chMaskTmp << (curBlock & 1 ? 8 : 0);
+              channel            = channel + (curBlock * 8);
+              JoinBlocksRemaining &= ~(1 << curBlock);
+              ChannelsMaskRemaining[curBlock / 2] &= ~chMaskTmp;
+              if ((JoinBlocksRemaining == 0)) {
+                JoinBlocksRemaining = 0xFF;
+              }
+              break;
+            }
+            else {
+              channel = (channel + 1) % 8;
+            }
+          }
         }
-        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
-        LoRaMacFlags.Bits.MacDone = 1;
+      }
+    }
+
+    // No next channel case should never happen since ScheduleTx has already
+    // checked for at least one enabled channel and if none re-enabled all
+    // channels.
+    // But if we find ourselves without a channel then randomly select one
+    if (i >= 8) {
+      channel = randr(0, 63);
     }
+  }
+  // Use 500 KHz channel
+  else {
+    channel = randr(0, 7);
+    for (i = 0; i < 8; i++) {
+      uint8_t curChannel = (channel + i) % 8;
+
+      if (((Join500KHzRemaining & (1 << curChannel)) != 0)) {
+        Join500KHzRemaining &= ~(1 << curChannel);
+        channel = 64 + curChannel;
+        if (Join500KHzRemaining == 0) {
+          Join500KHzRemaining = 0xFF;
+        }
+        break;
+      }
+    }
+  }
+
+  for (i = 0; i < nbEnabledChannels; i++) {
+    if (enabledChannels[i] == channel)
+      break;
+  }
+
+  if (i == nbEnabledChannels) {
+    channel = enabledChannels[randr(0, nbEnabledChannels - 1)];
+  }
+
+  LastJoinBlock = channel / 8;
+
+  return channel;
 }
-
-static void OnRadioRxTimeout( void )
-{
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
+#endif
+
+static bool SetNextChannel(TimerTime_t* time) {
+  uint8_t     nbEnabledChannels = 0;
+  uint8_t     delayTx           = 0;
+  uint8_t     enabledChannels[LORA_MAX_NB_CHANNELS];
+  TimerTime_t nextTxDelay = (TimerTime_t)(-1);
+
+  memset1(enabledChannels, 0, LORA_MAX_NB_CHANNELS);
+
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+  if (CountNbEnabled125kHzChannels(ChannelsMaskRemaining) == 0) {  // Restore default channels
+    memcpy1((uint8_t*)ChannelsMaskRemaining, (uint8_t*)ChannelsMask, 8);
+  }
+  if ((ChannelsDatarate >= DR_4) &&
+      ((ChannelsMaskRemaining[4] & 0x00FF) == 0)) {  // Make sure, that the channels are activated
+    ChannelsMaskRemaining[4] = ChannelsMask[4];
+  }
+#else
+  if (CountBits(ChannelsMask[0], 16) == 0) {
+    // Re-enable default channels, if no channel is enabled
+    ChannelsMask[0] = ChannelsMask[0] | (LC(1) + LC(2) + LC(3));
+  }
+#endif
+
+  // Update Aggregated duty cycle
+  if (AggregatedTimeOff <= TimerGetElapsedTime(AggregatedLastTxDoneTime)) {
+    AggregatedTimeOff = 0;
+
+    // Update bands Time OFF
+    for (uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++) {
+      if (DutyCycleOn == true) {
+        if (Bands[i].TimeOff <= TimerGetElapsedTime(Bands[i].LastTxDoneTime)) {
+          Bands[i].TimeOff = 0;
+        }
+        if (Bands[i].TimeOff != 0) {
+          nextTxDelay =
+            MIN(Bands[i].TimeOff - TimerGetElapsedTime(Bands[i].LastTxDoneTime), nextTxDelay);
+        }
+      }
+      else {
+        nextTxDelay      = 0;
+        Bands[i].TimeOff = 0;
+      }
+    }
+
+    // Search how many channels are enabled
+    for (uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++) {
+      for (uint8_t j = 0; j < 16; j++) {
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+        if ((ChannelsMaskRemaining[k] & (1 << j)) != 0)
+#else
+        if ((ChannelsMask[k] & (1 << j)) != 0)
+#endif
+        {
+          if (Channels[i + j].Frequency == 0) {  // Check if the channel is enabled
+            continue;
+          }
+#if defined(USE_BAND_868) || defined(USE_BAND_433) || defined(USE_BAND_780)
+          if (IsLoRaMacNetworkJoined == false) {
+            if ((JOIN_CHANNELS & (1 << j)) == 0) {
+              continue;
+            }
+          }
+#endif
+          if (((Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate) &&
+               (ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max)) ==
+              false) {  // Check if the current channel selection supports the
+                        // given datarate
+            continue;
+          }
+          if (Bands[Channels[i + j].Band].TimeOff >
+              0) {  // Check if the band is available for transmission
+            delayTx++;
+            continue;
+          }
+          enabledChannels[nbEnabledChannels++] = i + j;
+        }
+      }
+    }
+  }
+  else {
+    delayTx++;
+    nextTxDelay = AggregatedTimeOff - TimerGetElapsedTime(AggregatedLastTxDoneTime);
+  }
+
+  if (nbEnabledChannels > 0) {
+#if defined(USE_BAND_915)
+    if (IsLoRaMacNetworkJoined == false) {
+      Channel = GetNextJoinChannel(enabledChannels, nbEnabledChannels);
+    }
+    // Send first uplink on channel from same sub-band as the join
+    else if ((UpLinkCounter == 1) && (LastJoinBlock != -1)) {
+      uint8_t i;
+      uint8_t blockFirstChannel = LastJoinBlock * 8;
+
+      Channel = randr(blockFirstChannel, blockFirstChannel + 7);
+
+      // Check channel is enabled
+      for (i = 0; i < nbEnabledChannels; i++) {
+        if (Channel == enabledChannels[i])
+          break;
+      }
+
+      // If channel is not enabled fallback to selecting from the list of
+      // enabled  channels
+      if (i == nbEnabledChannels) {
+        Channel = enabledChannels[randr(0, nbEnabledChannels - 1)];
+      }
     }
     else
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    if( RxSlot == 1 )
-    {
-        if( NodeAckRequested == true )
-        {
-            McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
-        }
-        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
-        LoRaMacFlags.Bits.MacDone = 1;
-    }
-}
-
-static void OnMacStateCheckTimerEvent( void )
-{
-    TimerStop( &MacStateCheckTimer );
-    bool txTimeout = false;
-    bool txDone = false;
-
-    if( LoRaMacFlags.Bits.MacDone == 1 )
-    {
-        if( ( LoRaMacState & MAC_RX_ABORT ) == MAC_RX_ABORT )
-        {
-            LoRaMacState &= ~MAC_RX_ABORT;
-            LoRaMacState &= ~MAC_TX_RUNNING;
-        }
-
-        if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
-        {
-            if( ( McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) ||
-                ( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) )
-            {
-                // Stop transmit cycle due to tx timeout.
-                LoRaMacState &= ~MAC_TX_RUNNING;
-                McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
-                McpsConfirm.AckReceived = false;
-                McpsConfirm.TxTimeOnAir = 0;
-                txTimeout = true;
-            }
-        }
-
-        if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
-        {
-            if( LoRaMacFlags.Bits.MlmeReq == 1 )
-            {
-                if( MlmeConfirm.MlmeRequest == MLME_JOIN )
-                {
-                    if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
-                    {
-                        UpLinkCounter = 0;
-                    }
-                    // Join messages aren't repeated automatically
-                    ChannelsNbRepCounter = ChannelsNbRep;
-                }
-            }
-            if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
-            {
-                if( ( ChannelsNbRepCounter >= ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
-                {
-                    ChannelsNbRepCounter = 0;
-
-                    txDone = true;
-                    LoRaMacState &= ~MAC_TX_RUNNING;
-                }
-                else
-                {
-                    LoRaMacFlags.Bits.MacDone = 0;
-                    // Sends the same frame again
-                    ScheduleTx( );
-                }
-            }
-        }
-
-        if( LoRaMacFlags.Bits.McpsInd == 1 )
-        {
-            if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
-            {
-                AckTimeoutRetry = false;
-                NodeAckRequested = false;
-                txDone = true;
-                McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
-
-                LoRaMacState &= ~MAC_TX_RUNNING;
-            }
-        }
-
-        if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & MAC_TX_DELAYED ) == 0 ) )
-        {
-            AckTimeoutRetry = false;
-            if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
-            {
-                AckTimeoutRetriesCounter++;
-                
-                if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
-                {
-                    ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
-                    // Check if new datarate is valid for the Payload length
-					if( ValidatePayloadLength( LoRaMacBufferPktLen - 13, ChannelsDatarate, 0 ) == false )
-					{							
-						// If invalid payload length, then revert to previous datarate
-						ChannelsDatarate++;
-					}
-                }
-                LoRaMacFlags.Bits.MacDone = 0;
-                // Sends the same frame again
-                ScheduleTx( );
-            }
-            else
-            {
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-                // Re-enable default channels LC1, LC2, LC3
-                ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
-#elif !defined( USE_BAND_915 ) && !defined( USE_BAND_915_HYBRID )
-    #error "Please define a frequency band in the compiler options."
 #endif
-                LoRaMacState &= ~MAC_TX_RUNNING;
-
-                NodeAckRequested = false;
-                McpsConfirm.AckReceived = false;
-                McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
-                txDone = true;
-            }
-        }
-        
-        // Update uplink counter
-    	if( ( txDone == true ) && ( IsUpLinkCounterFixed == false ) )
-    	{	
-    		UpLinkCounter++;
-    		
-    		// Reset AdrAckCounter if downlink received
-    		if( ( LoRaMacFlags.Bits.McpsInd == 1 ) || ( UpLinkCounter == 1 ) )
-    		{
-    			AdrAckCounter = 0;
-    		}
-    		else
-    		{
-    			AdrAckCounter++;
-    		}
-    	}
-    }
-    // Handle reception for Class B and Class C
-    if( ( LoRaMacState & MAC_RX ) == MAC_RX )
-    {
-        LoRaMacState &= ~MAC_RX;
-    }
-    
-    if( LoRaMacState == MAC_IDLE )
-    {
-        if( LoRaMacFlags.Bits.McpsReq == 1 )
-        {
-            LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm );
-            LoRaMacFlags.Bits.McpsReq = 0;
-        }
-
-        if( LoRaMacFlags.Bits.MlmeReq == 1 )
-        {
-            LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm );
-            LoRaMacFlags.Bits.MlmeReq = 0;
-        }
-        
-        LoRaMacFlags.Bits.MacDone = 0;
-    }
-    else
-    {
-        // Operation not finished restart timer
-        TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
-        TimerStart( &MacStateCheckTimer );
-    }
-
-    if( LoRaMacFlags.Bits.McpsInd == 1 )
-    {
-        LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
-        LoRaMacFlags.Bits.McpsInd = 0;
-    }
-}
-
-static void OnTxDelayedTimerEvent( void )
-{
-    TimerStop( &TxDelayedTimer );
-    LoRaMacState &= ~MAC_TX_DELAYED;
-
-    ScheduleTx( );
-}
-
-static void OnRxWindow1TimerEvent( void )
-{
-    uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
-    int8_t datarate = 0;
-    uint32_t bandwidth = 0; // LoRa 125 kHz
-
-    TimerStop( &RxWindowTimer1 );
-    RxSlot = 0;
-
-    if( LoRaMacDeviceClass == CLASS_C )
-    {
-        Radio.Standby( );
-    }
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    datarate = ChannelsDatarate - Rx1DrOffset;
-    if( datarate < 0 )
-    {
-        datarate = DR_0;
-    }
-
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    if( ( datarate == DR_3 ) || ( datarate == DR_4 ) )
-    { // DR_4, DR_3
-        symbTimeout = 8;
-    }
-    else if( datarate == DR_5 )
-    {
-        symbTimeout = 10;
-    }
-    else if( datarate == DR_6 )
-    {// LoRa 250 kHz
-        bandwidth  = 1;
-        symbTimeout = 14;
-    }
-    RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset];
-    if( datarate < 0 )
-    {
-        datarate = DR_0;
-    }
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-
-
-	symbTimeout = 10;
-	// For low SF, we increase the number of symbols generating a Rx Timeout
-    switch ( datarate )
     {
-        case DR_0:
-        case DR_8:
-        case DR_9:
-        case DR_10:
-            symbTimeout += 5;
-        	break;
-        case DR_1:
-        case DR_11: 
-            symbTimeout += 8;
-            break;
-        case DR_2:
-        case DR_4:
-        case DR_12: 
-            symbTimeout += 9;
-            break;
-        case DR_3:
-        case DR_13: 
-            symbTimeout += 10;
-            break;
-        default:
-        	symbTimeout += 5;
-           break;
-    }
-
-    if( datarate >= DR_4 )
-    {// LoRa 500 kHz
-        bandwidth  = 2;
-    }
-    RxWindowSetup( 923.3e6 + ( Channel % 8 ) * 600e3, datarate, bandwidth, symbTimeout, false );
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-}
-
-static void OnRxWindow2TimerEvent( void )
-{
-    uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
-    uint32_t bandwidth = 0; // LoRa 125 kHz
-
-    TimerStop( &RxWindowTimer2 );
-    RxSlot = 1;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    if( ( Rx2Channel.Datarate == DR_3 ) || ( Rx2Channel.Datarate == DR_4 ) )
-    { // DR_4, DR_3
-        symbTimeout = 8;
-    }
-    else if( Rx2Channel.Datarate == DR_5 )
-    {
-        symbTimeout = 10;
-    }
-    else if( Rx2Channel.Datarate == DR_6 )
-    {// LoRa 250 kHz
-        bandwidth  = 1;
-        symbTimeout = 14;
-    }
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    switch( Rx2Channel.Datarate )
-    {
-        case DR_0:       // SF10 - BW125
-            symbTimeout = 5;
-            break;
-
-        case DR_1:       // SF9  - BW125
-        case DR_2:       // SF8  - BW125
-        case DR_8:       // SF12 - BW500
-        case DR_9:       // SF11 - BW500
-        case DR_10:      // SF10 - BW500
-            symbTimeout = 8;
-            break;
-
-        case DR_3:       // SF7  - BW125
-        case DR_11:      // SF9  - BW500
-            symbTimeout = 10;
-            break;
-
-        case DR_4:       // SF8  - BW500
-        case DR_12:      // SF8  - BW500
-            symbTimeout = 14;
-            break;
-
-        case DR_13:      // SF7  - BW500
-            symbTimeout = 16;
-            break;
-        default:
-            break;
-    }
-    if( Rx2Channel.Datarate >= DR_4 )
-    {// LoRa 500 kHz
-        bandwidth  = 2;
-    }
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, false );
-    }
-    else
-    {
-        RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, true );
-    }
-}
-
-static void OnAckTimeoutTimerEvent( void )
-{
-    TimerStop( &AckTimeoutTimer );
-
-    if( NodeAckRequested == true )
-    {
-        AckTimeoutRetry = true;
-        LoRaMacState &= ~MAC_ACK_REQ;
-    }
-    if( LoRaMacDeviceClass == CLASS_C )
-    {
-        LoRaMacFlags.Bits.MacDone = 1;
+      Channel = enabledChannels[randr(0, nbEnabledChannels - 1)];
     }
-}
-
-#if defined( USE_BAND_915 ) 
-uint8_t GetNextJoinChannel( uint8_t* enabledChannels, uint8_t nbEnabledChannels )
-{ 
-    int8_t   channel = -1;
-    uint8_t  block;
-    uint8_t  i;
-
-    // Use 125KHz channel
-    if( ChannelsDatarate < DR_4 )
-    {
-        block = JoinBlock[NextJoinBlock]; 
-        NextJoinBlock = (NextJoinBlock + 1) % 8;
-
-        // If next block is greater than max block then randomly select the next block   
-        if( block >= 8 )
-            block = randr(0, 7);
-
-        // Start search for next join channel at the selected block
-        for(i = 0; ( i < 8 ) && ( channel == -1 ); i++)
-        {
-            uint8_t curBlock = (block + i) % 8;
-            uint8_t chMask;
-
-            // Cycle through all blocks before using a previously used block             
-            if( ( ( JoinBlocksRemaining & ( 1 <<  curBlock ) ) != 0) ) 
-            {
-                chMask = ( ChannelsMaskRemaining[curBlock/2] >> ( curBlock & 1 ? 8 : 0 ) ) & 0xff; 
-                if( chMask != 0)
-                { 
-                    channel = randr(0, 7); 
-                    for(uint8_t i = 0; ( i < 8 ); i++)
-                    {                       
-                        if( ( chMask & ( 1 << channel ) ) != 0 )
-                        {
-                            uint16_t chMaskTmp = ( 1 << channel );
-                            chMaskTmp = chMaskTmp << ( curBlock & 1 ? 8 : 0 );
-                            channel = channel + ( curBlock * 8 );
-                            JoinBlocksRemaining &= ~(1 << curBlock);                                                        
-                            ChannelsMaskRemaining[curBlock/2] &= ~chMaskTmp;                            
-                            if( ( JoinBlocksRemaining == 0 ) )
-                            {
-                                JoinBlocksRemaining = 0xFF;
-                            }                           
-                            break;
-                        }
-                        else
-                        {
-                            channel = ( channel + 1 ) % 8;
-                        }
-                    }
-                }
-            }
-        }
-        
-        // No next channel case should never happen since ScheduleTx has already 
-        // checked for at least one enabled channel and if none re-enabled all channels. 
-        // But if we find ourselves without a channel then randomly select one
-        if ( i >= 8 )
-        {
-            channel = randr( 0, 63 );
-        }
-    }
-    // Use 500 KHz channel
-    else 
-    {
-        channel = randr( 0, 7 );
-        for(i = 0; i < 8; i++)
-        {
-            uint8_t curChannel = (channel + i) % 8;
-            
-            if( ( ( Join500KHzRemaining & ( 1 << curChannel ) ) != 0 ) )
-            {
-                Join500KHzRemaining &= ~(1 << curChannel);
-                channel = 64 + curChannel;
-                if( Join500KHzRemaining == 0 )
-                {
-                    Join500KHzRemaining = 0xFF;
-                }
-                break;
-            }
-        }
-    }
-
-    for( i = 0; i < nbEnabledChannels; i++ )
-    {
-        if( enabledChannels[i] == channel )
-            break;
-    }
-
-    if( i == nbEnabledChannels )
-    {
-        channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
-    }
-
-    LastJoinBlock = channel / 8;
-
-    return channel;
-}
-#endif
-
-static bool SetNextChannel( TimerTime_t* time )
-{
-    uint8_t nbEnabledChannels = 0;
-    uint8_t delayTx = 0;
-    uint8_t enabledChannels[LORA_MAX_NB_CHANNELS];
-    TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
-
-    memset1( enabledChannels, 0, LORA_MAX_NB_CHANNELS );
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 )
-    { // Restore default channels
-        memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 8 );
-    }
-    if( ( ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) )
-    { // Make sure, that the channels are activated
-        ChannelsMaskRemaining[4] = ChannelsMask[4];
-    }
-#else
-    if( CountBits( ChannelsMask[0], 16 ) == 0 )
-    {
-        // Re-enable default channels, if no channel is enabled
-        ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
+
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+    if (Channel < (LORA_MAX_NB_CHANNELS - 8)) {
+      DisableChannelInMask(Channel, ChannelsMaskRemaining);
     }
 #endif
-
-    // Update Aggregated duty cycle
-    if( AggregatedTimeOff <= TimerGetElapsedTime( AggregatedLastTxDoneTime ) )
-    {
-        AggregatedTimeOff = 0;
-
-        // Update bands Time OFF
-        for( uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++ )
-        {
-            if( DutyCycleOn == true )
-            {
-                if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) )
-                {
-                    Bands[i].TimeOff = 0;
-                }
-                if( Bands[i].TimeOff != 0 )
-                {
-                    nextTxDelay = MIN( Bands[i].TimeOff -
-                                       TimerGetElapsedTime( Bands[i].LastTxDoneTime ),
-                                       nextTxDelay );
-                }
-            }
-            else
-            {
-                nextTxDelay = 0;
-                Bands[i].TimeOff = 0;
-            }
-        }
-
-        // Search how many channels are enabled
-        for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
-        {
-            for( uint8_t j = 0; j < 16; j++ )
-            {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 )
-#else
-                if( ( ChannelsMask[k] & ( 1 << j ) ) != 0 )
-#endif
-                {
-                    if( Channels[i + j].Frequency == 0 )
-                    { // Check if the channel is enabled
-                        continue;
-                    }
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
-                    if( IsLoRaMacNetworkJoined == false )
-                    {
-                        if( ( JOIN_CHANNELS & ( 1 << j ) ) == 0 )
-                        {
-                            continue;
-                        }
-                    }
-#endif
-                    if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) &&
-                          ( ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false )
-                    { // Check if the current channel selection supports the given datarate
-                        continue;
-                    }
-                    if( Bands[Channels[i + j].Band].TimeOff > 0 )
-                    { // Check if the band is available for transmission
-                        delayTx++;
-                        continue;
-                    }
-                    enabledChannels[nbEnabledChannels++] = i + j;
-                }
-            }
-        }
-    }
-    else
-    {
-        delayTx++;
-        nextTxDelay = AggregatedTimeOff - TimerGetElapsedTime( AggregatedLastTxDoneTime );
+    *time = 0;
+    return true;
+  }
+  else {
+    if (delayTx > 0) {
+      // Delay transmission due to AggregatedTimeOff or to a band time off
+      *time = nextTxDelay;
+      return true;
     }
-    
-    if( nbEnabledChannels > 0 )
-    {
-#if defined( USE_BAND_915 ) 
-        if ( IsLoRaMacNetworkJoined == false )
-        {
-            Channel = GetNextJoinChannel(enabledChannels, nbEnabledChannels);
-        }
-        // Send first uplink on channel from same sub-band as the join 
-        else if( ( UpLinkCounter == 1 ) && ( LastJoinBlock != -1 ) )
-        {
-            uint8_t i;
-            uint8_t blockFirstChannel = LastJoinBlock*8;
-
-            Channel = randr( blockFirstChannel, blockFirstChannel + 7 );
-
-            // Check channel is enabled
-            for( i = 0; i < nbEnabledChannels; i++ )
-            {
-                if( Channel == enabledChannels[i] )
-                    break;
-            }
-
-            // If channel is not enabled fallback to selecting from the list of 
-            // enabled  channels
-            if (i == nbEnabledChannels)
-            {
-                Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
-            }
-        }
-        else
+    // Datarate not supported by any channel
+    *time = 0;
+    return false;
+  }
+}
+
+static void SetPublicNetwork(bool enable) {
+  PublicNetwork = enable;
+  Radio.SetModem(MODEM_LORA);
+  if (PublicNetwork == true) {
+    // Change LoRa modem SyncWord
+    Radio.Write(REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD);
+  }
+  else {
+    // Change LoRa modem SyncWord
+    Radio.Write(REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD);
+  }
+}
+
+static void RxWindowSetup(uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout,
+                          bool rxContinuous) {
+  uint8_t       downlinkDatarate = Datarates[datarate];
+  RadioModems_t modem;
+
+  if (Radio.GetStatus() == RF_IDLE) {
+    Radio.SetChannel(freq);
+
+    // Store downlink datarate
+    McpsIndication.RxDatarate = (uint8_t)datarate;
+
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+    if (datarate == DR_7) {
+      modem = MODEM_FSK;
+      Radio.SetRxConfig(modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0,
+                        0, false, rxContinuous);
+    }
+    else {
+      modem = MODEM_LORA;
+      Radio.SetRxConfig(modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0,
+                        true, rxContinuous);
+    }
+#elif defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+    modem = MODEM_LORA;
+    Radio.SetRxConfig(modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0,
+                      true, rxContinuous);
 #endif
-        { 
-            Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
-        }
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-        if( Channel < ( LORA_MAX_NB_CHANNELS - 8 ) )
-        {
-            DisableChannelInMask( Channel, ChannelsMaskRemaining );
-        }
-#endif
-        *time = 0;
-        return true;
+
+    if (RepeaterSupport == true) {
+      Radio.SetMaxPayloadLength(
+        modem, MaxPayloadOfDatarateRepeater[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD);
+    }
+    else {
+      Radio.SetMaxPayloadLength(modem,
+                                MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD);
+    }
+
+    if (rxContinuous == false) {
+      Radio.Rx(MaxRxWindow);
+    }
+    else {
+      Radio.Rx(0);  // Continuous mode
     }
-    else
-    {
-        if( delayTx > 0 )
-        {
-            // Delay transmission due to AggregatedTimeOff or to a band time off
-            *time = nextTxDelay;
-            return true;
-        }
-        // Datarate not supported by any channel
-        *time = 0;
-        return false;
-    }
+  }
 }
 
-static void SetPublicNetwork( bool enable )
-{
-    PublicNetwork = enable;
-    Radio.SetModem( MODEM_LORA );
-    if( PublicNetwork == true )
-    {
-        // Change LoRa modem SyncWord
-        Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
-    }
-    else
-    {
-        // Change LoRa modem SyncWord
-        Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
-    }
+static bool Rx2FreqInRange(uint32_t freq) {
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+  if (Radio.CheckRfFrequency(freq) == true)
+#elif (defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+  if ((Radio.CheckRfFrequency(freq) == true) && (freq >= LORAMAC_FIRST_RX2_CHANNEL) &&
+      (freq <= LORAMAC_LAST_RX2_CHANNEL) && (((freq - (uint32_t)LORAMAC_FIRST_RX2_CHANNEL) %
+                                              (uint32_t)LORAMAC_STEPWIDTH_RX2_CHANNEL) == 0))
+#endif
+  {
+    return true;
+  }
+  return false;
 }
 
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
-{
-    uint8_t downlinkDatarate = Datarates[datarate];
-    RadioModems_t modem;
-
-    if( Radio.GetStatus( ) == RF_IDLE )
-    {
-        Radio.SetChannel( freq );
-
-        // Store downlink datarate
-        McpsIndication.RxDatarate = ( uint8_t ) datarate;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-        if( datarate == DR_7 )
-        {
-            modem = MODEM_FSK;
-            Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, rxContinuous );
-        }
-        else
-        {
-            modem = MODEM_LORA;
-            Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
-        }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-        modem = MODEM_LORA;
-        Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
-#endif
-
-        if( RepeaterSupport == true )
-        {
-            Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRepeater[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
-        }
-        else
-        {
-            Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
-        }
-
-        if( rxContinuous == false )
-        {
-            Radio.Rx( MaxRxWindow );
-        }
-        else
-        {
-            Radio.Rx( 0 ); // Continuous mode
-        }
+static bool ValidatePayloadLength(uint8_t lenN, int8_t datarate, uint8_t fOptsLen) {
+  uint16_t maxN        = 0;
+  uint16_t payloadSize = 0;
+
+  // Get the maximum payload length
+  if (RepeaterSupport == true) {
+    maxN = MaxPayloadOfDatarateRepeater[datarate];
+  }
+  else {
+    maxN = MaxPayloadOfDatarate[datarate];
+  }
+
+  // Calculate the resulting payload size
+  payloadSize = (lenN + fOptsLen);
+
+  // Validation of the application payload size
+  if ((payloadSize <= maxN) && (payloadSize <= LORAMAC_PHY_MAXPAYLOAD)) {
+    return true;
+  }
+  return false;
+}
+
+static uint8_t CountBits(uint16_t mask, uint8_t nbBits) {
+  uint8_t nbActiveBits = 0;
+
+  for (uint8_t j = 0; j < nbBits; j++) {
+    if ((mask & (1 << j)) == (1 << j)) {
+      nbActiveBits++;
     }
-}
-
-static bool Rx2FreqInRange( uint32_t freq )
-{
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( Radio.CheckRfFrequency( freq ) == true )
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    if( ( Radio.CheckRfFrequency( freq ) == true ) &&
-        ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) &&
-        ( freq <= LORAMAC_LAST_RX2_CHANNEL ) &&
-        ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) )
-#endif
-    {
-        return true;
-    }
-    return false;
+  }
+  return nbActiveBits;
 }
 
-
-static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
-{
-    uint16_t maxN = 0;
-    uint16_t payloadSize = 0;
-
-    // Get the maximum payload length
-    if( RepeaterSupport == true )
-    {
-        maxN = MaxPayloadOfDatarateRepeater[datarate];
-    }
-    else
-    {
-        maxN = MaxPayloadOfDatarate[datarate];
-    }
-
-    // Calculate the resulting payload size
-    payloadSize = ( lenN + fOptsLen );
-
-    // Validation of the application payload size
-    if( ( payloadSize <= maxN ) && ( payloadSize <= LORAMAC_PHY_MAXPAYLOAD ) )
-    {
-        return true;
-    }
-    return false;
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+static uint8_t CountNbEnabled125kHzChannels(uint16_t* channelsMask) {
+  uint8_t nb125kHzChannels = 0;
+
+  for (uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++) {
+    nb125kHzChannels += CountBits(channelsMask[k], 16);
+  }
+
+  return nb125kHzChannels;
 }
 
-static uint8_t CountBits( uint16_t mask, uint8_t nbBits )
-{
-    uint8_t nbActiveBits = 0;
-
-    for( uint8_t j = 0; j < nbBits; j++ )
-    {
-        if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
-        {
-            nbActiveBits++;
-        }
+#if defined(USE_BAND_915_HYBRID)
+static void ReenableChannels(uint16_t mask, uint16_t* channelMask) {
+  uint16_t blockMask = mask;
+
+  for (uint8_t i = 0, j = 0; i < 4; i++, j += 2) {
+    channelMask[i] = 0;
+    if ((blockMask & (1 << j)) != 0) {
+      channelMask[i] |= 0x00FF;
     }
-    return nbActiveBits;
-}
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask )
-{
-    uint8_t nb125kHzChannels = 0;
-
-    for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
-    {
-        nb125kHzChannels += CountBits( channelsMask[k], 16 );
-    }
-
-    return nb125kHzChannels;
-}
-
-#if defined( USE_BAND_915_HYBRID )
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask )
-{
-    uint16_t blockMask = mask;
-
-    for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
-    {
-        channelMask[i] = 0;
-        if( ( blockMask & ( 1 << j ) ) != 0 )
-        {
-            channelMask[i] |= 0x00FF;
-        }
-        if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
-        {
-            channelMask[i] |= 0xFF00;
-        }
+    if ((blockMask & (1 << (j + 1))) != 0) {
+      channelMask[i] |= 0xFF00;
     }
-    channelMask[4] = blockMask;
-    channelMask[5] = 0x0000;
+  }
+  channelMask[4] = blockMask;
+  channelMask[5] = 0x0000;
 }
 
-static bool ValidateChannelMask( uint16_t* channelMask )
-{
-    bool chanMaskState = false;
-    uint16_t block1 = 0;
-    uint16_t block2 = 0;
-    uint8_t index = 0;
-
-    for( uint8_t i = 0; i < 4; i++ )
-    {
-        block1 = channelMask[i] & 0x00FF;
-        block2 = channelMask[i] & 0xFF00;
-
-        if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) )
-        {
-            channelMask[i] &= block1;
-            channelMask[4] = 1 << ( i * 2 );
-            chanMaskState = true;
-            index = i;
-        }
-        else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) )
-        {
-            channelMask[i] &= block2;
-            channelMask[4] = 1 << ( i * 2 + 1 );
-            chanMaskState = true;
-            index = i;
-        }
+static bool ValidateChannelMask(uint16_t* channelMask) {
+  bool     chanMaskState = false;
+  uint16_t block1        = 0;
+  uint16_t block2        = 0;
+  uint8_t  index         = 0;
+
+  for (uint8_t i = 0; i < 4; i++) {
+    block1 = channelMask[i] & 0x00FF;
+    block2 = channelMask[i] & 0xFF00;
+
+    if ((CountBits(block1, 16) > 5) && (chanMaskState == false)) {
+      channelMask[i] &= block1;
+      channelMask[4] = 1 << (i * 2);
+      chanMaskState  = true;
+      index          = i;
     }
-
-    // Do only change the channel mask, if we have found a valid block.
-    if( chanMaskState == true )
-    {
-        for( uint8_t i = 0; i < 4; i++ )
-        {
-            if( i != index )
-            {
-                channelMask[i] = 0;
-            }
-        }
+    else if ((CountBits(block2, 16) > 5) && (chanMaskState == false)) {
+      channelMask[i] &= block2;
+      channelMask[4] = 1 << (i * 2 + 1);
+      chanMaskState  = true;
+      index          = i;
     }
-    return chanMaskState;
+  }
+
+  // Do only change the channel mask, if we have found a valid block.
+  if (chanMaskState == true) {
+    for (uint8_t i = 0; i < 4; i++) {
+      if (i != index) {
+        channelMask[i] = 0;
+      }
+    }
+  }
+  return chanMaskState;
 }
 #endif
 #endif
 
-static int8_t LimitTxPower( int8_t txPower )
-{
-    int8_t resultTxPower =  MAX( txPower, TX_POWER_30_DBM );
-
-    return resultTxPower;
+static int8_t LimitTxPower(int8_t txPower) {
+  int8_t resultTxPower = MAX(txPower, TX_POWER_30_DBM);
+
+  return resultTxPower;
 }
 
-static bool ValueInRange( int8_t value, int8_t min, int8_t max )
-{
-    if( ( value >= min ) && ( value <= max ) )
-    {
-        return true;
-    }
-    return false;
+static bool ValueInRange(int8_t value, int8_t min, int8_t max) {
+  if ((value >= min) && (value <= max)) {
+    return true;
+  }
+  return false;
 }
 
-static bool DisableChannelInMask( uint8_t id, uint16_t* mask )
-{
-    uint8_t index = 0;
-    index = id / 16;
-
-    if( ( index > 4 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
-    {
-        return false;
-    }
-
-    // Deactivate channel
-    mask[index] &= ~( 1 << ( id % 16 ) );
-
-    return true;
+static bool DisableChannelInMask(uint8_t id, uint16_t* mask) {
+  uint8_t index = 0;
+  index         = id / 16;
+
+  if ((index > 4) || (id >= LORA_MAX_NB_CHANNELS)) {
+    return false;
+  }
+
+  // Deactivate channel
+  mask[index] &= ~(1 << (id % 16));
+
+  return true;
 }
 
-static bool AdrNextDr( bool adrEnabled, bool isTx, int8_t* datarateOut, int8_t* txpowerOut )
-{
-    bool adrAckReq = false;
-    int8_t datarate = ChannelsDatarate;
-    int8_t txpower  = ChannelsTxPower;
-    
-    if( adrEnabled == true )
-    {
-        /* Request ADR Ack Request (including at lowest available datarate) */
-        adrAckReq = AdrAckCounter >= ADR_ACK_LIMIT ? true : false;
-
-        if( AdrAckCounter >= (ADR_ACK_LIMIT + ADR_ACK_DELAY) )
-        {
-            // Step up power
-            txpower = LORAMAC_DEFAULT_TX_POWER;
-
-            if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 )
-            {
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-                if( datarate > LORAMAC_TX_MIN_DATARATE )
-                {
-                	datarate--;
-                }
-
-                if( datarate == LORAMAC_TX_MIN_DATARATE )
-                {
-                	if( isTx == true )
-                	{
-                		// Re-enable default channels LC1, LC2, LC3
-                		ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
-                	}
-                }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                if( datarate > LORAMAC_TX_MIN_DATARATE )
-                {
-                	if ( datarate == DR_8)
-                		datarate = DR_4;
-                	else
-                		datarate--;
-                		
-                }
-                else if( isTx == true )
-                {
-#if defined( USE_BAND_915 )
-                	// Re-enable default channels
-                	ChannelsMask[0] = 0xFFFF;
-                	ChannelsMask[1] = 0xFFFF;
-                	ChannelsMask[2] = 0xFFFF;
-                	ChannelsMask[3] = 0xFFFF;
-                	ChannelsMask[4] = 0x00FF;
-                	ChannelsMask[5] = 0x0000;
-#else // defined( USE_BAND_915_HYBRID )
-                	// Re-enable default channels
-                	ChannelsMask[0] = 0x00FF;
-                	ChannelsMask[1] = 0x0000;
-                	ChannelsMask[2] = 0x0000;
-                	ChannelsMask[3] = 0x0000;
-                	ChannelsMask[4] = 0x0001;
-                	ChannelsMask[5] = 0x0000;
+static bool AdrNextDr(bool adrEnabled, bool isTx, int8_t* datarateOut, int8_t* txpowerOut) {
+  bool   adrAckReq = false;
+  int8_t datarate  = ChannelsDatarate;
+  int8_t txpower   = ChannelsTxPower;
+
+  if (adrEnabled == true) {
+    /* Request ADR Ack Request (including at lowest available datarate) */
+    adrAckReq = AdrAckCounter >= ADR_ACK_LIMIT ? true : false;
+
+    if (AdrAckCounter >= (ADR_ACK_LIMIT + ADR_ACK_DELAY)) {
+      // Step up power
+      txpower = LORAMAC_DEFAULT_TX_POWER;
+
+      if ((AdrAckCounter % ADR_ACK_DELAY) == 0) {
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+        if (datarate > LORAMAC_TX_MIN_DATARATE) {
+          datarate--;
+        }
+
+        if (datarate == LORAMAC_TX_MIN_DATARATE) {
+          if (isTx == true) {
+            // Re-enable default channels LC1, LC2, LC3
+            ChannelsMask[0] = ChannelsMask[0] | (LC(1) + LC(2) + LC(3));
+          }
+        }
+#elif defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+        if (datarate > LORAMAC_TX_MIN_DATARATE) {
+          if (datarate == DR_8)
+            datarate = DR_4;
+          else
+            datarate--;
+        }
+        else if (isTx == true) {
+#if defined(USE_BAND_915)
+          // Re-enable default channels
+          ChannelsMask[0] = 0xFFFF;
+          ChannelsMask[1] = 0xFFFF;
+          ChannelsMask[2] = 0xFFFF;
+          ChannelsMask[3] = 0xFFFF;
+          ChannelsMask[4] = 0x00FF;
+          ChannelsMask[5] = 0x0000;
+#else  // defined( USE_BAND_915_HYBRID )
+          // Re-enable default channels
+          ChannelsMask[0] = 0x00FF;
+          ChannelsMask[1] = 0x0000;
+          ChannelsMask[2] = 0x0000;
+          ChannelsMask[3] = 0x0000;
+          ChannelsMask[4] = 0x0001;
+          ChannelsMask[5] = 0x0000;
 #endif
-                }
+        }
 #else
 #error "Please define a frequency band in the compiler options."
 #endif
-            }
-        }
+      }
     }
-
-    if(datarateOut != NULL)
-        *datarateOut = datarate;
-
-    if(txpowerOut != NULL)
-        *txpowerOut = txpower;
-
-    return adrAckReq;
-    
+  }
+
+  if (datarateOut != NULL)
+    *datarateOut = datarate;
+
+  if (txpowerOut != NULL)
+    *txpowerOut = txpower;
+
+  return adrAckReq;
 }
 
-static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
-    // The maximum buffer length must take MAC commands to re-send into account.
-    uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
-
-    switch( cmd )
-    {
-        case MOTE_MAC_LINK_CHECK_REQ:
-            if( MacCommandsBufferIndex < bufLen )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // No payload for this command
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_LINK_ADR_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 1 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // Margin
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_DUTY_CYCLE_ANS:
-            if( MacCommandsBufferIndex < bufLen )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // No payload for this answer
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_RX_PARAM_SETUP_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 1 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // Status: Datarate ACK, Channel ACK
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_DEV_STATUS_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 2 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // 1st byte Battery
-                // 2nd byte Margin
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_NEW_CHANNEL_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 1 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // Status: Datarate range OK, Channel frequency OK
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_RX_TIMING_SETUP_ANS:
-            if( MacCommandsBufferIndex < bufLen )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // No payload for this answer
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        default:
-            return LORAMAC_STATUS_SERVICE_UNKNOWN;
+static LoRaMacStatus_t AddMacCommand(uint8_t cmd, uint8_t p1, uint8_t p2) {
+  LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
+  // The maximum buffer length must take MAC commands to re-send into account.
+  uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
+
+  switch (cmd) {
+    case MOTE_MAC_LINK_CHECK_REQ:
+      if (MacCommandsBufferIndex < bufLen) {
+        MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+        // No payload for this command
+        status = LORAMAC_STATUS_OK;
+      }
+      break;
+    case MOTE_MAC_LINK_ADR_ANS:
+      if (MacCommandsBufferIndex < (bufLen - 1)) {
+        MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+        // Margin
+        MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
+        status                                      = LORAMAC_STATUS_OK;
+      }
+      break;
+    case MOTE_MAC_DUTY_CYCLE_ANS:
+      if (MacCommandsBufferIndex < bufLen) {
+        MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+        // No payload for this answer
+        status = LORAMAC_STATUS_OK;
+      }
+      break;
+    case MOTE_MAC_RX_PARAM_SETUP_ANS:
+      if (MacCommandsBufferIndex < (bufLen - 1)) {
+        MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+        // Status: Datarate ACK, Channel ACK
+        MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
+        status                                      = LORAMAC_STATUS_OK;
+      }
+      break;
+    case MOTE_MAC_DEV_STATUS_ANS:
+      if (MacCommandsBufferIndex < (bufLen - 2)) {
+        MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+        // 1st byte Battery
+        // 2nd byte Margin
+        MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
+        MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
+        status                                      = LORAMAC_STATUS_OK;
+      }
+      break;
+    case MOTE_MAC_NEW_CHANNEL_ANS:
+      if (MacCommandsBufferIndex < (bufLen - 1)) {
+        MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+        // Status: Datarate range OK, Channel frequency OK
+        MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
+        status                                      = LORAMAC_STATUS_OK;
+      }
+      break;
+    case MOTE_MAC_RX_TIMING_SETUP_ANS:
+      if (MacCommandsBufferIndex < bufLen) {
+        MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
+        // No payload for this answer
+        status = LORAMAC_STATUS_OK;
+      }
+      break;
+    default:
+      return LORAMAC_STATUS_SERVICE_UNKNOWN;
+  }
+  if (status == LORAMAC_STATUS_OK) {
+    MacCommandsInNextTx = true;
+  }
+  return status;
+}
+
+static uint8_t ParseMacCommandsToRepeat(uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut) {
+  uint8_t i        = 0;
+  uint8_t cmdCount = 0;
+
+  if ((cmdBufIn == NULL) || (cmdBufOut == NULL)) {
+    return 0;
+  }
+
+  for (i = 0; i < length; i++) {
+    switch (cmdBufIn[i]) {
+      case MOTE_MAC_RX_PARAM_SETUP_ANS: {
+        cmdBufOut[cmdCount++] = cmdBufIn[i++];
+        cmdBufOut[cmdCount++] = cmdBufIn[i++];
+        cmdBufOut[cmdCount++] = cmdBufIn[i];
+        break;
+      }
+      case MOTE_MAC_RX_TIMING_SETUP_ANS: {
+        cmdBufOut[cmdCount++] = cmdBufIn[i];
+        break;
+      }
+      default:
+        break;
     }
-    if( status == LORAMAC_STATUS_OK )
-    {
-        MacCommandsInNextTx = true;
-    }
-    return status;
-}
-
-static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut )
-{
-    uint8_t i = 0;
-    uint8_t cmdCount = 0;
-
-    if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) )
-    {
-        return 0;
-    }
-
-    for( i = 0; i < length; i++ )
-    {
-        switch( cmdBufIn[i] )
-        {
-            case MOTE_MAC_RX_PARAM_SETUP_ANS:
-            {
-                cmdBufOut[cmdCount++] = cmdBufIn[i++];
-                cmdBufOut[cmdCount++] = cmdBufIn[i++];
-                cmdBufOut[cmdCount++] = cmdBufIn[i];
-                break;
-            }
-            case MOTE_MAC_RX_TIMING_SETUP_ANS:
-            {
-                cmdBufOut[cmdCount++] = cmdBufIn[i];
-                break;
-            }
-            default:
-                break;
-        }
-    }
-
-    return cmdCount;
+  }
+
+  return cmdCount;
 }
 
-static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
-{
-    uint8_t  validLinkAdrCmds = 0;
-    int8_t   txPower          = 0;
-    int8_t   datarate         = 0;
-    uint8_t  nbRep            = 0;
-    uint16_t channelsMask[6]  = {0,0,0,0,0,0}; 
-    uint8_t  LinkAdrMacCmdBufferIndex = 0;
-
-    while( macIndex < commandsSize )
-    {
-        // Decode Frame MAC commands
-        switch( payload[macIndex++] )
-        {
-            case SRV_MAC_LINK_CHECK_ANS:
-                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                MlmeConfirm.DemodMargin = payload[macIndex++];
-                MlmeConfirm.NbGateways = payload[macIndex++];
-                break;
-            case SRV_MAC_LINK_ADR_REQ:
-                {
-                    uint8_t  chMaskCntl = 0;
-                    uint8_t  status     = 0x07; 
-                    uint16_t chMask;
-
-                    datarate = payload[macIndex++];
-                    txPower  = datarate & 0x0F;
-                    datarate = ( datarate >> 4 ) & 0x0F;
-
-                    if( ( AdrCtrlOn == false ) &&
-                        ( ( ChannelsDatarate != datarate ) || ( ChannelsTxPower != txPower ) ) )
-                    { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower
-                        // Answer the server with fail status
-                        // Power ACK     = 0
-                        // Data rate ACK = 0
-                        // Channel mask  = 0
-                        AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 );
-                        macIndex += 3;  // Skip over the remaining bytes of the request
-                        break;
-                    }
-                    else if ( validLinkAdrCmds++ == 0 )
-                    {
-                        // Initialize local copy of the channels mask array
-                        for(uint8_t i = 0; i < 6; i++ )
-                        {
-                            channelsMask[i] = ChannelsMask[i];
-                        }
-                    }
-
-
-                    chMask = ( uint16_t )payload[macIndex++];
-                    chMask |= ( uint16_t )payload[macIndex++] << 8;
-
-                    nbRep = payload[macIndex++];
-                    chMaskCntl = ( nbRep >> 4 ) & 0x07;
-                    nbRep &= 0x0F;
-                    if( nbRep == 0 )
-                    {
-                        nbRep = 1;
-                    }
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-                    if( ( chMaskCntl == 0 ) && ( chMask == 0 ) )
-                    {
-                        status &= 0xFE; // Channel mask KO
-                    }
-                    else if( ( ( chMaskCntl >= 1 ) && ( chMaskCntl <= 5 )) ||
-                             ( chMaskCntl >= 7 ) )
-                    {
-                        // RFU
-                        status &= 0xFE; // Channel mask KO
-                    }
-                    else
-                    {
-                        for( i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
-                        {
-                            if( chMaskCntl == 6 )
-                            {
-                                if( Channels[i].Frequency != 0 )
-                                {
-                                    chMask |= 1 << i;
-                                }
-                            }
-                            else
-                            {
-                                if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
-                                    ( Channels[i].Frequency == 0 ) )
-                                {// Trying to enable an undefined channel
-                                    status &= 0xFE; // Channel mask KO
-                                }
-                            }
-                        }
-                        channelsMask[0] = chMask;
-                    }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                    if( chMaskCntl < 4 )
-                    {
-                        channelsMask[chMaskCntl] = chMask;
-                    }
-                    else if( chMaskCntl == 6 )
-                    {
-                        // Enable all 125 kHz channels
-                        for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
-                        {
-                            for( uint8_t j = 0; j < 16; j++ )
-                            {
-                                if( Channels[i + j].Frequency != 0 )
-                                {
-                                    channelsMask[k] |= 1 << j;
-                                }
-                            }
-                        }
-                        // channel mask applied to 500 kHz channels
-                        channelsMask[4] =  chMask; 
-                    }
-                    else if( chMaskCntl == 7 )
-                    {
-                        // Disable all 125 kHz channels
-                        channelsMask[0] = 0x0000;
-                        channelsMask[1] = 0x0000;
-                        channelsMask[2] = 0x0000;
-                        channelsMask[3] = 0x0000;
-
-                        // channel mask applied to 500 kHz channels
-                        channelsMask[4] = chMask;
-                    }
-                    else 
-                    {
-                        // RFU
-                        status &= 0xFE; // Channel mask KO
-                    }
+static void ProcessMacCommands(uint8_t* payload, uint8_t macIndex, uint8_t commandsSize,
+                               uint8_t snr) {
+  uint8_t  validLinkAdrCmds         = 0;
+  int8_t   txPower                  = 0;
+  int8_t   datarate                 = 0;
+  uint8_t  nbRep                    = 0;
+  uint16_t channelsMask[6]          = {0, 0, 0, 0, 0, 0};
+  uint8_t  LinkAdrMacCmdBufferIndex = 0;
+
+  while (macIndex < commandsSize) {
+    // Decode Frame MAC commands
+    switch (payload[macIndex++]) {
+      case SRV_MAC_LINK_CHECK_ANS:
+        MlmeConfirm.Status      = LORAMAC_EVENT_INFO_STATUS_OK;
+        MlmeConfirm.DemodMargin = payload[macIndex++];
+        MlmeConfirm.NbGateways  = payload[macIndex++];
+        break;
+      case SRV_MAC_LINK_ADR_REQ: {
+        uint8_t  chMaskCntl = 0;
+        uint8_t  status     = 0x07;
+        uint16_t chMask;
+
+        datarate = payload[macIndex++];
+        txPower  = datarate & 0x0F;
+        datarate = (datarate >> 4) & 0x0F;
+
+        if ((AdrCtrlOn == false) &&
+            ((ChannelsDatarate != datarate) ||
+             (ChannelsTxPower != txPower))) {  // ADR disabled don't handle ADR
+                                               // requests if server tries to
+                                               // change datarate or txpower
+          // Answer the server with fail status
+          // Power ACK     = 0
+          // Data rate ACK = 0
+          // Channel mask  = 0
+          AddMacCommand(MOTE_MAC_LINK_ADR_ANS, 0, 0);
+          macIndex += 3;  // Skip over the remaining bytes of the request
+          break;
+        }
+        else if (validLinkAdrCmds++ == 0) {
+          // Initialize local copy of the channels mask array
+          for (uint8_t i = 0; i < 6; i++) {
+            channelsMask[i] = ChannelsMask[i];
+          }
+        }
+
+        chMask = (uint16_t)payload[macIndex++];
+        chMask |= (uint16_t)payload[macIndex++] << 8;
+
+        nbRep      = payload[macIndex++];
+        chMaskCntl = (nbRep >> 4) & 0x07;
+        nbRep &= 0x0F;
+        if (nbRep == 0) {
+          nbRep = 1;
+        }
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+        if ((chMaskCntl == 0) && (chMask == 0)) {
+          status &= 0xFE;  // Channel mask KO
+        }
+        else if (((chMaskCntl >= 1) && (chMaskCntl <= 5)) || (chMaskCntl >= 7)) {
+          // RFU
+          status &= 0xFE;  // Channel mask KO
+        }
+        else {
+          for (i = 0; i < LORA_MAX_NB_CHANNELS; i++) {
+            if (chMaskCntl == 6) {
+              if (Channels[i].Frequency != 0) {
+                chMask |= 1 << i;
+              }
+            }
+            else {
+              if (((chMask & (1 << i)) != 0) &&
+                  (Channels[i].Frequency == 0)) {  // Trying to enable an undefined channel
+                status &= 0xFE;                    // Channel mask KO
+              }
+            }
+          }
+          channelsMask[0] = chMask;
+        }
+#elif defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+        if (chMaskCntl < 4) {
+          channelsMask[chMaskCntl] = chMask;
+        }
+        else if (chMaskCntl == 6) {
+          // Enable all 125 kHz channels
+          for (uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++) {
+            for (uint8_t j = 0; j < 16; j++) {
+              if (Channels[i + j].Frequency != 0) {
+                channelsMask[k] |= 1 << j;
+              }
+            }
+          }
+          // channel mask applied to 500 kHz channels
+          channelsMask[4] = chMask;
+        }
+        else if (chMaskCntl == 7) {
+          // Disable all 125 kHz channels
+          channelsMask[0] = 0x0000;
+          channelsMask[1] = 0x0000;
+          channelsMask[2] = 0x0000;
+          channelsMask[3] = 0x0000;
+
+          // channel mask applied to 500 kHz channels
+          channelsMask[4] = chMask;
+        }
+        else {
+          // RFU
+          status &= 0xFE;  // Channel mask KO
+        }
 #else
-    #error "Please define a frequency band in the compiler options."
+#error "Please define a frequency band in the compiler options."
 #endif
-                    if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
-                    {
-                        status &= 0xFD; // Datarate KO
-                    }
-
-                    //
-                    // Remark MaxTxPower = 0 and MinTxPower = 5
-                    //
-                    if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) == false )
-                    {
-                        status &= 0xFB; // TxPower KO
-                    } 
-
-
-                    // Save the mac command status location for possible channel mask KO later
-                    LinkAdrMacCmdBufferIndex = MacCommandsBufferIndex;
-
-                    AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
-                }
-                break;
-            case SRV_MAC_DUTY_CYCLE_REQ:
-                MaxDCycle = payload[macIndex++];
-                AggregatedDCycle = 1 << MaxDCycle;
-                AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS, 0, 0 );
-                break;
-            case SRV_MAC_RX_PARAM_SETUP_REQ:
-                {
-                    uint8_t status = 0x07;
-                    int8_t datarate = 0;
-                    int8_t drOffset = 0;
-                    uint32_t freq = 0;
-
-                    drOffset = ( payload[macIndex] >> 4 ) & 0x07;
-                    datarate = payload[macIndex] & 0x0F;
-                    macIndex++;
-
-                    freq =  ( uint32_t )payload[macIndex++];
-                    freq |= ( uint32_t )payload[macIndex++] << 8;
-                    freq |= ( uint32_t )payload[macIndex++] << 16;
-                    freq *= 100;
-                    
-                    if( Rx2FreqInRange( freq ) == false )
-                    {
-                        status &= 0xFE; // Channel frequency KO
-                    }
-
-                    if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false )
-                    {
-                        status &= 0xFD; // Datarate KO
-                    }
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-                    if( ( ValueInRange( datarate, DR_5, DR_7 ) == true ) ||
-                        ( datarate > DR_13 ) )
-                    {
-                        status &= 0xFD; // Datarate KO
-                    }
+        if (ValueInRange(datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE) == false) {
+          status &= 0xFD;  // Datarate KO
+        }
+
+        //
+        // Remark MaxTxPower = 0 and MinTxPower = 5
+        //
+        if (ValueInRange(txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER) == false) {
+          status &= 0xFB;  // TxPower KO
+        }
+
+        // Save the mac command status location for possible channel mask KO
+        // later
+        LinkAdrMacCmdBufferIndex = MacCommandsBufferIndex;
+
+        AddMacCommand(MOTE_MAC_LINK_ADR_ANS, status, 0);
+      } break;
+      case SRV_MAC_DUTY_CYCLE_REQ:
+        MaxDCycle        = payload[macIndex++];
+        AggregatedDCycle = 1 << MaxDCycle;
+        AddMacCommand(MOTE_MAC_DUTY_CYCLE_ANS, 0, 0);
+        break;
+      case SRV_MAC_RX_PARAM_SETUP_REQ: {
+        uint8_t  status   = 0x07;
+        int8_t   datarate = 0;
+        int8_t   drOffset = 0;
+        uint32_t freq     = 0;
+
+        drOffset = (payload[macIndex] >> 4) & 0x07;
+        datarate = payload[macIndex] & 0x0F;
+        macIndex++;
+
+        freq = (uint32_t)payload[macIndex++];
+        freq |= (uint32_t)payload[macIndex++] << 8;
+        freq |= (uint32_t)payload[macIndex++] << 16;
+        freq *= 100;
+
+        if (Rx2FreqInRange(freq) == false) {
+          status &= 0xFE;  // Channel frequency KO
+        }
+
+        if (ValueInRange(datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE) == false) {
+          status &= 0xFD;  // Datarate KO
+        }
+#if (defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+        if ((ValueInRange(datarate, DR_5, DR_7) == true) || (datarate > DR_13)) {
+          status &= 0xFD;  // Datarate KO
+        }
 #endif
-                    if( ValueInRange( drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET ) == false )
-                    {
-                        status &= 0xFB; // Rx1DrOffset range KO
-                    }
-
-                    if( ( status & 0x07 ) == 0x07 )
-                    {
-                        Rx2Channel.Datarate = datarate;
-                        Rx2Channel.Frequency = freq;
-                        Rx1DrOffset = drOffset;
-                    }
-                    AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
-                }
-                break;
-            case SRV_MAC_DEV_STATUS_REQ:
-                {
-                    uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
-                    if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) )
-                    {
-                        batteryLevel = LoRaMacCallbacks->GetBatteryLevel( );
-                    }
-                    AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr );
-                    break;
-                }
-            case SRV_MAC_NEW_CHANNEL_REQ:
-                {
-                    uint8_t status = 0x03;
-
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-                    status &= 0xFC; // Channel frequency and datarate KO
-                    macIndex += 5;
+        if (ValueInRange(drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET) == false) {
+          status &= 0xFB;  // Rx1DrOffset range KO
+        }
+
+        if ((status & 0x07) == 0x07) {
+          Rx2Channel.Datarate  = datarate;
+          Rx2Channel.Frequency = freq;
+          Rx1DrOffset          = drOffset;
+        }
+        AddMacCommand(MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0);
+      } break;
+      case SRV_MAC_DEV_STATUS_REQ: {
+        uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
+        if ((LoRaMacCallbacks != NULL) && (LoRaMacCallbacks->GetBatteryLevel != NULL)) {
+          batteryLevel = LoRaMacCallbacks->GetBatteryLevel();
+        }
+        AddMacCommand(MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr);
+        break;
+      }
+      case SRV_MAC_NEW_CHANNEL_REQ: {
+        uint8_t status = 0x03;
+
+#if (defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+        status &= 0xFC;  // Channel frequency and datarate KO
+        macIndex += 5;
 #else
-                    int8_t channelIndex = 0;
-                    ChannelParams_t chParam;
-
-                    channelIndex = payload[macIndex++];
-                    chParam.Frequency = ( uint32_t )payload[macIndex++];
-                    chParam.Frequency |= ( uint32_t )payload[macIndex++] << 8;
-                    chParam.Frequency |= ( uint32_t )payload[macIndex++] << 16;
-                    chParam.Frequency *= 100;
-                    chParam.DrRange.Value = payload[macIndex++];
-
-                    LoRaMacState |= MAC_TX_CONFIG;
-                    if( chParam.Frequency == 0 )
-                    {
-                        if( channelIndex < 3 )
-                        {
-                            status &= 0xFC;
-                        }
-                        else
-                        {
-                            if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK )
-                            {
-                                status &= 0xFC;
-                            }
-                        }
-                    }
-                    else
-                    {
-                        switch( LoRaMacChannelAdd( channelIndex, chParam ) )
-                        {
-                            case LORAMAC_STATUS_OK:
-                            {
-                                break;
-                            }
-                            case LORAMAC_STATUS_FREQUENCY_INVALID:
-                            {
-                                status &= 0xFE;
-                                break;
-                            }
-                            case LORAMAC_STATUS_DATARATE_INVALID:
-                            {
-                                status &= 0xFD;
-                                break;
-                            }
-                            case LORAMAC_STATUS_FREQ_AND_DR_INVALID:
-                            {
-                                status &= 0xFC;
-                                break;
-                            }
-                            default:
-                            {
-                                status &= 0xFC;
-                                break;
-                            }
-                        }
-                    }
-                    LoRaMacState &= ~MAC_TX_CONFIG;
+        int8_t          channelIndex = 0;
+        ChannelParams_t chParam;
+
+        channelIndex      = payload[macIndex++];
+        chParam.Frequency = (uint32_t)payload[macIndex++];
+        chParam.Frequency |= (uint32_t)payload[macIndex++] << 8;
+        chParam.Frequency |= (uint32_t)payload[macIndex++] << 16;
+        chParam.Frequency *= 100;
+        chParam.DrRange.Value = payload[macIndex++];
+
+        LoRaMacState |= MAC_TX_CONFIG;
+        if (chParam.Frequency == 0) {
+          if (channelIndex < 3) {
+            status &= 0xFC;
+          }
+          else {
+            if (LoRaMacChannelRemove(channelIndex) != LORAMAC_STATUS_OK) {
+              status &= 0xFC;
+            }
+          }
+        }
+        else {
+          switch (LoRaMacChannelAdd(channelIndex, chParam)) {
+            case LORAMAC_STATUS_OK: {
+              break;
+            }
+            case LORAMAC_STATUS_FREQUENCY_INVALID: {
+              status &= 0xFE;
+              break;
+            }
+            case LORAMAC_STATUS_DATARATE_INVALID: {
+              status &= 0xFD;
+              break;
+            }
+            case LORAMAC_STATUS_FREQ_AND_DR_INVALID: {
+              status &= 0xFC;
+              break;
+            }
+            default: {
+              status &= 0xFC;
+              break;
+            }
+          }
+        }
+        LoRaMacState &= ~MAC_TX_CONFIG;
 #endif
-                    AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
-                }
-                break;
-            case SRV_MAC_RX_TIMING_SETUP_REQ:
-                {
-                    uint8_t delay = payload[macIndex++] & 0x0F;
-
-                    if( delay == 0 )
-                    {
-                        delay++;
-                    }
-                    ReceiveDelay1 = delay * 1e6;
-                    ReceiveDelay2 = ReceiveDelay1 + 1e6;
-                    AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
-                }
-                break;
-            default:
-                // Unknown command. ABORT MAC commands processing
-                return;
+        AddMacCommand(MOTE_MAC_NEW_CHANNEL_ANS, status, 0);
+      } break;
+      case SRV_MAC_RX_TIMING_SETUP_REQ: {
+        uint8_t delay = payload[macIndex++] & 0x0F;
+
+        if (delay == 0) {
+          delay++;
         }
+        ReceiveDelay1 = delay * 1e6;
+        ReceiveDelay2 = ReceiveDelay1 + 1e6;
+        AddMacCommand(MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0);
+      } break;
+      default:
+        // Unknown command. ABORT MAC commands processing
+        return;
     }
-
-    // Process accumulated Link ADR channel mask changes
-    if( validLinkAdrCmds > 0 ) 
-    {
-        uint8_t drOkCounter = 0;
-        uint8_t status      = 0x07;
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-        for(uint8_t i=0; i< 6; i++)
-        {
-            for( uint8_t j = 0; j < 16; j++ )
-            {
-                if( ( channelsMask[i] & ( 1 << j ) ) != 0 ) 
-                {
-                    if ( ( Channels[i * 16 + j].Frequency == 0 ) )
-                    {
-                        status &= 0xFE; // Channel mask KO
-                        break;
-                    }
-                    else if( ( datarate >= Channels[i * 16 + j].DrRange.Fields.Min ) &&
-                             ( datarate <= Channels[i * 16 + j].DrRange.Fields.Max ) ) 
-                    {
-                        drOkCounter++;
-                    }
-                }
-            }
+  }
+
+  // Process accumulated Link ADR channel mask changes
+  if (validLinkAdrCmds > 0) {
+    uint8_t drOkCounter = 0;
+    uint8_t status      = 0x07;
+
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+    for (uint8_t i = 0; i < 6; i++) {
+      for (uint8_t j = 0; j < 16; j++) {
+        if ((channelsMask[i] & (1 << j)) != 0) {
+          if ((Channels[i * 16 + j].Frequency == 0)) {
+            status &= 0xFE;  // Channel mask KO
+            break;
+          }
+          else if ((datarate >= Channels[i * 16 + j].DrRange.Fields.Min) &&
+                   (datarate <= Channels[i * 16 + j].DrRange.Fields.Max)) {
+            drOkCounter++;
+          }
         }
-
-        if ( drOkCounter == 0 )
-        {
-            status &= 0xFD;  // Datarate KO
-        }
-
-        if( ( CountNbEnabled125kHzChannels( channelsMask ) > 0 ) && ( CountNbEnabled125kHzChannels( channelsMask ) < HYBRD_CHNLS_MIN ) )
-        {
-            status &= 0xFE; // Channel mask KO
-        }
-
-#if defined( USE_BAND_915_HYBRID )
-        if( ValidateChannelMask( channelsMask ) == false )
-        {
-            status &= 0xFE; // Channel mask KO
-        }
+      }
+    }
+
+    if (drOkCounter == 0) {
+      status &= 0xFD;  // Datarate KO
+    }
+
+    if ((CountNbEnabled125kHzChannels(channelsMask) > 0) &&
+        (CountNbEnabled125kHzChannels(channelsMask) < HYBRD_CHNLS_MIN)) {
+      status &= 0xFE;  // Channel mask KO
+    }
+
+#if defined(USE_BAND_915_HYBRID)
+    if (ValidateChannelMask(channelsMask) == false) {
+      status &= 0xFE;  // Channel mask KO
+    }
 #endif
 
 #endif
-        if( ( status & 0x07 ) == 0x07 )
-        {
-            ChannelsDatarate = datarate;
-			ChannelsDefaultDatarate = datarate;
-            ChannelsTxPower = txPower;
-
-            ChannelsMask[0] = channelsMask[0];
-            ChannelsMask[1] = channelsMask[1];
-            ChannelsMask[2] = channelsMask[2];
-            ChannelsMask[3] = channelsMask[3];
-            ChannelsMask[4] = channelsMask[4];
-            ChannelsMask[5] = channelsMask[5];
-
-            ChannelsNbRep = nbRep; 
-            
-            // Clear remaining channels mask
-            memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 10 );
-        }
-        // Channel Mask KO
-        else
-        {
-            // Update the last Link ADR status with channel mask KO
-            if( (LinkAdrMacCmdBufferIndex+1 ) < LORA_MAC_COMMAND_MAX_LENGTH )
-                MacCommandsBuffer[LinkAdrMacCmdBufferIndex+1] &= status;
-        }
-    }
-}
-
-LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    LoRaMacFrameCtrl_t fCtrl;
-    LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
-
-    fCtrl.Value = 0;
-    fCtrl.Bits.FOptsLen      = 0;
-    fCtrl.Bits.FPending      = 0;
-    fCtrl.Bits.Ack           = false;
-    fCtrl.Bits.AdrAckReq     = false;
-    fCtrl.Bits.Adr           = AdrCtrlOn;
-
-    // Prepare the frame
-    status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize );
-
-    // Validate status
-    if( status != LORAMAC_STATUS_OK )
-    {
-        return status;
-    }
-
-    // Reset confirm parameters
-    McpsConfirm.NbRetries = 0;
-    McpsConfirm.AckReceived = false;
-    McpsConfirm.UpLinkCounter = UpLinkCounter;
-
-    status = ScheduleTx( );
-
-    return status;
-}
-
-static LoRaMacStatus_t ScheduleTx( )
-{
-    TimerTime_t dutyCycleTimeOff = 0;
-
-    // Check if the device is off
-    if( MaxDCycle == 255 )
-    {
-        return LORAMAC_STATUS_DEVICE_OFF;
-    }
-    if( MaxDCycle == 0 )
-    {
-        AggregatedTimeOff = 0;
+    if ((status & 0x07) == 0x07) {
+      ChannelsDatarate        = datarate;
+      ChannelsDefaultDatarate = datarate;
+      ChannelsTxPower         = txPower;
+
+      ChannelsMask[0] = channelsMask[0];
+      ChannelsMask[1] = channelsMask[1];
+      ChannelsMask[2] = channelsMask[2];
+      ChannelsMask[3] = channelsMask[3];
+      ChannelsMask[4] = channelsMask[4];
+      ChannelsMask[5] = channelsMask[5];
+
+      ChannelsNbRep = nbRep;
+
+      // Clear remaining channels mask
+      memcpy1((uint8_t*)ChannelsMaskRemaining, (uint8_t*)ChannelsMask, 10);
     }
-
-    CalculateBackOff( LastTxChannel );
-
-    // Select channel
-    while( SetNextChannel( &dutyCycleTimeOff ) == false )
-    {
-        // Set the default datarate
-        ChannelsDatarate = ChannelsDefaultDatarate;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-        // Re-enable default channels LC1, LC2, LC3
-        ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
-#endif
-    }
-
-    // Schedule transmission of frame
-    if( dutyCycleTimeOff == 0 )
-    {
-        // Try to send now
-        return SendFrameOnChannel( Channels[Channel] );
-    }
-    else
-    {
-        // Send later - prepare timer
-        LoRaMacState |= MAC_TX_DELAYED;
-        TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
-        TimerStart( &TxDelayedTimer );
-
-        return LORAMAC_STATUS_OK;
-    }
-}
-
-static void CalculateBackOff( uint8_t channel )
-{
-    uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
-
-    if( IsLoRaMacNetworkJoined == false )
-    {
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
-        dutyCycle = JOIN_DC;
-#endif
-    }
-
-    // Update Band Time OFF
-    if( DutyCycleOn == true )
-    {
-        Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
-    }
-    else
-    {
-        Bands[Channels[channel].Band].TimeOff = 0;
-    }
-    // Update Aggregated Time OFF
-    AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
-}
-
-LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    uint16_t i;
-    uint8_t pktHeaderLen = 0;
-    uint32_t mic = 0;
-    const void* payload = fBuffer;
-    uint8_t payloadSize = fBufferSize;
-    uint8_t framePort = fPort;
-
-    LoRaMacBufferPktLen = 0;
-
-    NodeAckRequested = false;
-
-    if( fBuffer == NULL )
-    {
-        fBufferSize = 0;
+    // Channel Mask KO
+    else {
+      // Update the last Link ADR status with channel mask KO
+      if ((LinkAdrMacCmdBufferIndex + 1) < LORA_MAC_COMMAND_MAX_LENGTH)
+        MacCommandsBuffer[LinkAdrMacCmdBufferIndex + 1] &= status;
     }
-
-    LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
-
-    switch( macHdr->Bits.MType )
-    {
-        case FRAME_TYPE_JOIN_REQ:
-            RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
-            RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
-
-            LoRaMacBufferPktLen = pktHeaderLen;
-
-            memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
-            LoRaMacBufferPktLen += 8;
-            memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8 );
-            LoRaMacBufferPktLen += 8;
-
-            LoRaMacDevNonce = Radio.Random( );
-
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF;
-
-            LoRaMacJoinComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic );
-
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
-
-            break;
-        case FRAME_TYPE_DATA_CONFIRMED_UP:
-            NodeAckRequested = true;
-            //Intentional falltrough
-        case FRAME_TYPE_DATA_UNCONFIRMED_UP:
-            if( IsLoRaMacNetworkJoined == false )
-            {
-                return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
-            }
-
-            fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate, &ChannelsTxPower );
-
-            if( ValidatePayloadLength( fBufferSize, ChannelsDatarate, MacCommandsBufferIndex ) == false )
-            {
-                return LORAMAC_STATUS_LENGTH_ERROR;
-            }
-
-            RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME;
-            RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME;
-
-            if( SrvAckRequested == true )
-            {
-                SrvAckRequested = false;
-                fCtrl->Bits.Ack = 1;
-            }
-
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;
-
-            LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;
-
-            LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
-
-            // Copy the MAC commands which must be re-send into the MAC command buffer
-            memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
-            MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
-
-            if( ( payload != NULL ) && ( payloadSize > 0 ) )
-            {
-                if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
-                {
-                    fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
-
-                    // Update FCtrl field with new value of OptionsLength
-                    LoRaMacBuffer[0x05] = fCtrl->Value;
-                    for( i = 0; i < MacCommandsBufferIndex; i++ )
-                    {
-                        LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
-                    }
-                }
-            }
-            else
-            {
-                if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
-                {
-                    payloadSize = MacCommandsBufferIndex;
-                    payload = MacCommandsBuffer;
-                    framePort = 0;
-                }
-            }
-            MacCommandsInNextTx = false;
-            // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
-            MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat );
-            if( MacCommandsBufferToRepeatIndex > 0 )
-            {
-                MacCommandsInNextTx = true;
-            }
-            MacCommandsBufferIndex = 0;
-
-            if( ( payload != NULL ) && ( payloadSize > 0 ) )
-            {
-                LoRaMacBuffer[pktHeaderLen++] = framePort;
-
-                if( framePort == 0 )
-                {
-                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
-                }
-                else
-                {
-                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
-                }
-                memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize );
-            }
-            LoRaMacBufferPktLen = pktHeaderLen + payloadSize;
-
-            LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
-
-            LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
-
-            LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
-
-            break;
-        case FRAME_TYPE_PROPRIETARY:
-            if( ( fBuffer != NULL ) && ( fBufferSize > 0 ) )
-            {
-                memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, fBufferSize );
-                LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
-            }
-            break;
-        default:
-            return LORAMAC_STATUS_SERVICE_UNKNOWN;
-    }
-
-    return LORAMAC_STATUS_OK;
+  }
 }
 
-LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel )
-{
-    int8_t datarate = Datarates[ChannelsDatarate];
-    int8_t txPowerIndex = 0;
-    int8_t txPower = 0;
-
-    txPowerIndex = LimitTxPower( ChannelsTxPower );
-    txPower = TxPowers[txPowerIndex];
-
-    MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-    McpsConfirm.Datarate = ChannelsDatarate;
-    McpsConfirm.TxPower = txPowerIndex;
-
-    Radio.SetChannel( channel.Frequency );
-    
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( ChannelsDatarate == DR_7 )
-    { // High Speed FSK channel
-        Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
-
-    }
-    else if( ChannelsDatarate == DR_6 )
-    { // High speed LoRa channel
-        Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-    else
-    { // Normal LoRa channel
-        Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-    if( ChannelsDatarate >= DR_4 )
-    { // High speed LoRa channel BW500 kHz
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-    else
-    { // Normal LoRa channel
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-
-    // Store the time on air
-    McpsConfirm.TxTimeOnAir = TxTimeOnAir;
-    MlmeConfirm.TxTimeOnAir = TxTimeOnAir;
-
-    // Starts the MAC layer status check timer
-    TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
-    TimerStart( &MacStateCheckTimer );
-
-    // Send now
-    Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
-
-    LoRaMacState |= MAC_TX_RUNNING;
-
-    return LORAMAC_STATUS_OK;
+LoRaMacStatus_t Send(LoRaMacHeader_t* macHdr, uint8_t fPort, void* fBuffer, uint16_t fBufferSize) {
+  LoRaMacFrameCtrl_t fCtrl;
+  LoRaMacStatus_t    status = LORAMAC_STATUS_PARAMETER_INVALID;
+
+  fCtrl.Value          = 0;
+  fCtrl.Bits.FOptsLen  = 0;
+  fCtrl.Bits.FPending  = 0;
+  fCtrl.Bits.Ack       = false;
+  fCtrl.Bits.AdrAckReq = false;
+  fCtrl.Bits.Adr       = AdrCtrlOn;
+
+  // Prepare the frame
+  status = PrepareFrame(macHdr, &fCtrl, fPort, fBuffer, fBufferSize);
+
+  // Validate status
+  if (status != LORAMAC_STATUS_OK) {
+    return status;
+  }
+
+  // Reset confirm parameters
+  McpsConfirm.NbRetries     = 0;
+  McpsConfirm.AckReceived   = false;
+  McpsConfirm.UpLinkCounter = UpLinkCounter;
+
+  status = ScheduleTx();
+
+  return status;
 }
 
-
-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks )
-{
-    if( primitives == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    if( ( primitives->MacMcpsConfirm == NULL ) ||
-        ( primitives->MacMcpsIndication == NULL ) ||
-        ( primitives->MacMlmeConfirm == NULL ))
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    LoRaMacPrimitives = primitives;
-    LoRaMacCallbacks = callbacks;
-
-    LoRaMacFlags.Value = 0;
-
-    LoRaMacDeviceClass = CLASS_A;
-
-    UpLinkCounter = 1;
-    DownLinkCounter = 0;
-    AdrAckCounter = 0;
-
-    ChannelsNbRepCounter = 0;
-
-    AckTimeoutRetries = 1;
-    AckTimeoutRetriesCounter = 1;
-    AckTimeoutRetry = false;
-
-    MaxDCycle = 0;
-    AggregatedDCycle = 1;
-
-    MacCommandsBufferIndex = 0;
-    MacCommandsBufferToRepeatIndex = 0;
-
-    IsRxWindowsEnabled = true;
-
-    RepeaterSupport = false;
-    IsRxWindowsEnabled = true;
-    IsLoRaMacNetworkJoined = false;
-    LoRaMacState = MAC_IDLE;
-
-    NodeAckRequested = false;
-    SrvAckRequested = false;
-    MacCommandsInNextTx = false;
-
-#if defined( USE_BAND_433 )
-    ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
-#elif defined( USE_BAND_780 )
-    ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
-#elif defined( USE_BAND_868 )
-    ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
-#elif defined( USE_BAND_915 )
-    ChannelsMask[0] = 0xFFFF;
-    ChannelsMask[1] = 0xFFFF;
-    ChannelsMask[2] = 0xFFFF;
-    ChannelsMask[3] = 0xFFFF;
-    ChannelsMask[4] = 0x00FF;
-    ChannelsMask[5] = 0x0000;
-
-    memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );
-#elif defined( USE_BAND_915_HYBRID )
-    ChannelsMask[0] = 0x00FF;
-    ChannelsMask[1] = 0x0000;
-    ChannelsMask[2] = 0x0000;
-    ChannelsMask[3] = 0x0000;
-    ChannelsMask[4] = 0x0001;
-    ChannelsMask[5] = 0x0000;
-
-    memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    // 125 kHz channels
-    for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ )
-    {
-        Channels[i].Frequency = 902.3e6 + i * 200e3;
-        Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
-        Channels[i].Band = 0;
-    }
-    // 500 kHz channels
-    for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ )
-    {
-        Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6;
-        Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
-        Channels[i].Band = 0;
-    }
+static LoRaMacStatus_t ScheduleTx() {
+  TimerTime_t dutyCycleTimeOff = 0;
+
+  // Check if the device is off
+  if (MaxDCycle == 255) {
+    return LORAMAC_STATUS_DEVICE_OFF;
+  }
+  if (MaxDCycle == 0) {
+    AggregatedTimeOff = 0;
+  }
+
+  CalculateBackOff(LastTxChannel);
+
+  // Select channel
+  while (SetNextChannel(&dutyCycleTimeOff) == false) {
+    // Set the default datarate
+    ChannelsDatarate = ChannelsDefaultDatarate;
+
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+    // Re-enable default channels LC1, LC2, LC3
+    ChannelsMask[0] = ChannelsMask[0] | (LC(1) + LC(2) + LC(3));
 #endif
-
-    ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
-    ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
-    ChannelsNbRep = 1;
-    ChannelsNbRepCounter = 0;
-
-	Rx2Channel.Frequency = 923300000;
-    Rx2Channel.Datarate = DR_8;
-    Rx1DrOffset = 0;
-
-
-    MaxDCycle = 0;
-    AggregatedDCycle = 1;
-    AggregatedLastTxDoneTime = 0;
-    AggregatedTimeOff = 0;
-
-#if defined( USE_BAND_433 )
-    DutyCycleOn = false;
-#elif defined( USE_BAND_780 )
-    DutyCycleOn = false;
-#elif defined( USE_BAND_868 )
-    DutyCycleOn = true;
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    DutyCycleOn = false;
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-
-    MaxRxWindow = MAX_RX_WINDOW;
-    ReceiveDelay1 = RECEIVE_DELAY1;
-    ReceiveDelay2 = RECEIVE_DELAY2;
-    JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
-    JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
-
-#if defined( USE_BAND_915 ) 
-    NextJoinBlock = 0;
-    LastJoinBlock = -1;
-    JoinBlocksRemaining = 0xff;
-    Join500KHzRemaining = 0xff;
-#endif
-
-    LastJoinTxTime  = 0;
-    JoinAggTimeOnAir = 0; 
-
-    TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
-    TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
-
-    TimerInit( &TxDelayedTimer, OnTxDelayedTimerEvent );
-    TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent );
-    TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
-    TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
-
-    // Initialize Radio driver
-    RadioEvents.TxDone = OnRadioTxDone;
-    RadioEvents.RxDone = OnRadioRxDone;
-    RadioEvents.RxError = OnRadioRxError;
-    RadioEvents.TxTimeout = OnRadioTxTimeout;
-    RadioEvents.RxTimeout = OnRadioRxTimeout;
-    Radio.Init( &RadioEvents );
-
-    // Random seed initialization
-    srand1( Radio.Random( ) );
-
-    // Initialize channel index.
-    Channel = LORA_MAX_NB_CHANNELS;
-
-    PublicNetwork = true;
-    SetPublicNetwork( PublicNetwork );
-    Radio.Sleep( );
-
-    return LORAMAC_STATUS_OK;
-}
-
-LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
-{
-    int8_t  datarate = ChannelsDefaultDatarate;
-    uint8_t fOptLen  = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
-
-    if( txInfo == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    AdrNextDr( AdrCtrlOn, false, &datarate, NULL );
-
-    if( RepeaterSupport == true )
-    {
-        txInfo->CurrentPayloadSize = MaxPayloadOfDatarateRepeater[datarate];
-    }
-    else
-    {
-        txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
-    }
-
-    if( txInfo->CurrentPayloadSize >= fOptLen )
-    {
-        txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
-    }
-    else
-    {
-        return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
-    }
-
-    if( ValidatePayloadLength( size, datarate, 0 ) == false )
-    {
-        return LORAMAC_STATUS_LENGTH_ERROR;
-    }
-
-    if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
-    {
-        return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
-    }
+  }
+
+  // Schedule transmission of frame
+  if (dutyCycleTimeOff == 0) {
+    // Try to send now
+    return SendFrameOnChannel(Channels[Channel]);
+  }
+  else {
+    // Send later - prepare timer
+    LoRaMacState |= MAC_TX_DELAYED;
+    TimerSetValue(&TxDelayedTimer, dutyCycleTimeOff);
+    TimerStart(&TxDelayedTimer);
 
     return LORAMAC_STATUS_OK;
+  }
 }
 
-LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_OK;
-
-    if( mibGet == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    switch( mibGet->Type )
-    {
-        case MIB_DEVICE_CLASS:
-        {
-            mibGet->Param.Class = LoRaMacDeviceClass;
-            break;
-        }
-        case MIB_NETWORK_JOINED:
-        {
-            mibGet->Param.IsNetworkJoined = IsLoRaMacNetworkJoined;
-            break;
-        }
-        case MIB_ADR:
-        {
-            mibGet->Param.AdrEnable = AdrCtrlOn;
-            break;
-        }
-        case MIB_NET_ID:
-        {
-            mibGet->Param.NetID = LoRaMacNetID;
-            break;
-        }
-        case MIB_DEV_ADDR:
-        {
-            mibGet->Param.DevAddr = LoRaMacDevAddr;
-            break;
-        }
-        case MIB_NWK_SKEY:
-        {
-            mibGet->Param.NwkSKey = LoRaMacNwkSKey;
-            break;
-        }
-        case MIB_APP_SKEY:
-        {
-            mibGet->Param.AppSKey = LoRaMacAppSKey;
-            break;
-        }
-        case MIB_PUBLIC_NETWORK:
-        {
-            mibGet->Param.EnablePublicNetwork = PublicNetwork;
-            break;
-        }
-        case MIB_REPEATER_SUPPORT:
-        {
-            mibGet->Param.EnableRepeaterSupport = RepeaterSupport;
-            break;
-        }
-        case MIB_CHANNELS:
-        {
-            mibGet->Param.ChannelList = Channels;
-            break;
-        }
-        case MIB_RX2_CHANNEL:
-        {
-            mibGet->Param.Rx2Channel = Rx2Channel;
-            break;
-        }
-        case MIB_CHANNELS_MASK:
-        {
-            mibGet->Param.ChannelsMask = ChannelsMask;
-            break;
-        }
-        case MIB_CHANNELS_NB_REP:
-        {
-            mibGet->Param.ChannelNbRep = ChannelsNbRep;
-            break;
-        }
-        case MIB_MAX_RX_WINDOW_DURATION:
-        {
-            mibGet->Param.MaxRxWindow = MaxRxWindow;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_1:
-        {
-            mibGet->Param.ReceiveDelay1 = ReceiveDelay1;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_2:
-        {
-            mibGet->Param.ReceiveDelay2 = ReceiveDelay2;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_1:
-        {
-            mibGet->Param.JoinAcceptDelay1 = JoinAcceptDelay1;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_2:
-        {
-            mibGet->Param.JoinAcceptDelay2 = JoinAcceptDelay2;
-            break;
-        }
-        case MIB_CHANNELS_DEFAULT_DATARATE:
-        {
-            mibGet->Param.ChannelsDefaultDatarate = ChannelsDefaultDatarate;
-            break;
+static void CalculateBackOff(uint8_t channel) {
+  uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
+
+  if (IsLoRaMacNetworkJoined == false) {
+#if defined(USE_BAND_868) || defined(USE_BAND_433) || defined(USE_BAND_780)
+    dutyCycle = JOIN_DC;
+#endif
+  }
+
+  // Update Band Time OFF
+  if (DutyCycleOn == true) {
+    Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
+  }
+  else {
+    Bands[Channels[channel].Band].TimeOff = 0;
+  }
+  // Update Aggregated Time OFF
+  AggregatedTimeOff = AggregatedTimeOff + (TxTimeOnAir * AggregatedDCycle - TxTimeOnAir);
+}
+
+LoRaMacStatus_t PrepareFrame(LoRaMacHeader_t* macHdr, LoRaMacFrameCtrl_t* fCtrl, uint8_t fPort,
+                             void* fBuffer, uint16_t fBufferSize) {
+  uint16_t    i;
+  uint8_t     pktHeaderLen = 0;
+  uint32_t    mic          = 0;
+  const void* payload      = fBuffer;
+  uint8_t     payloadSize  = fBufferSize;
+  uint8_t     framePort    = fPort;
+
+  LoRaMacBufferPktLen = 0;
+
+  NodeAckRequested = false;
+
+  if (fBuffer == NULL) {
+    fBufferSize = 0;
+  }
+
+  LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
+
+  switch (macHdr->Bits.MType) {
+    case FRAME_TYPE_JOIN_REQ:
+      RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
+      RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
+
+      LoRaMacBufferPktLen = pktHeaderLen;
+
+      memcpyr(LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8);
+      LoRaMacBufferPktLen += 8;
+      memcpyr(LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8);
+      LoRaMacBufferPktLen += 8;
+
+      LoRaMacDevNonce = Radio.Random();
+
+      LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
+      LoRaMacBuffer[LoRaMacBufferPktLen++] = (LoRaMacDevNonce >> 8) & 0xFF;
+
+      LoRaMacJoinComputeMic(LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic);
+
+      LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
+      LoRaMacBuffer[LoRaMacBufferPktLen++] = (mic >> 8) & 0xFF;
+      LoRaMacBuffer[LoRaMacBufferPktLen++] = (mic >> 16) & 0xFF;
+      LoRaMacBuffer[LoRaMacBufferPktLen++] = (mic >> 24) & 0xFF;
+
+      break;
+    case FRAME_TYPE_DATA_CONFIRMED_UP:
+      NodeAckRequested = true;
+    // Intentional falltrough
+    case FRAME_TYPE_DATA_UNCONFIRMED_UP:
+      if (IsLoRaMacNetworkJoined == false) {
+        return LORAMAC_STATUS_NO_NETWORK_JOINED;  // No network has been joined
+                                                  // yet
+      }
+
+      fCtrl->Bits.AdrAckReq = AdrNextDr(fCtrl->Bits.Adr, true, &ChannelsDatarate, &ChannelsTxPower);
+
+      if (ValidatePayloadLength(fBufferSize, ChannelsDatarate, MacCommandsBufferIndex) == false) {
+        return LORAMAC_STATUS_LENGTH_ERROR;
+      }
+
+      RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME;
+      RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME;
+
+      if (SrvAckRequested == true) {
+        SrvAckRequested = false;
+        fCtrl->Bits.Ack = 1;
+      }
+
+      LoRaMacBuffer[pktHeaderLen++] = (LoRaMacDevAddr)&0xFF;
+      LoRaMacBuffer[pktHeaderLen++] = (LoRaMacDevAddr >> 8) & 0xFF;
+      LoRaMacBuffer[pktHeaderLen++] = (LoRaMacDevAddr >> 16) & 0xFF;
+      LoRaMacBuffer[pktHeaderLen++] = (LoRaMacDevAddr >> 24) & 0xFF;
+
+      LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;
+
+      LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
+      LoRaMacBuffer[pktHeaderLen++] = (UpLinkCounter >> 8) & 0xFF;
+
+      // Copy the MAC commands which must be re-send into the MAC command buffer
+      memcpy1(&MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat,
+              MacCommandsBufferToRepeatIndex);
+      MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
+
+      if ((payload != NULL) && (payloadSize > 0)) {
+        if ((MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH) &&
+            (MacCommandsInNextTx == true)) {
+          fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
+
+          // Update FCtrl field with new value of OptionsLength
+          LoRaMacBuffer[0x05] = fCtrl->Value;
+          for (i = 0; i < MacCommandsBufferIndex; i++) {
+            LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
+          }
         }
-        case MIB_CHANNELS_DATARATE:
-        {
-            mibGet->Param.ChannelsDatarate = ChannelsDatarate;
-            break;
-        }
-        case MIB_CHANNELS_TX_POWER:
-        {
-            mibGet->Param.ChannelsTxPower = ChannelsTxPower;
-            break;
-        }
-        case MIB_UPLINK_COUNTER:
-        {
-            mibGet->Param.UpLinkCounter = UpLinkCounter;
-            break;
-        }
-        case MIB_DOWNLINK_COUNTER:
-        {
-            mibGet->Param.DownLinkCounter = DownLinkCounter;
-            break;
-        }
-        case MIB_MULTICAST_CHANNEL:
-        {
-            mibGet->Param.MulticastList = MulticastChannels;
-            break;
+      }
+      else {
+        if ((MacCommandsBufferIndex > 0) && (MacCommandsInNextTx)) {
+          payloadSize = MacCommandsBufferIndex;
+          payload     = MacCommandsBuffer;
+          framePort   = 0;
         }
-        default:
-            status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-            break;
-    }
-
-    return status;
-}
-
-LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_OK;
-
-    if( mibSet == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    switch( mibSet->Type )
-    {
-        case MIB_DEVICE_CLASS:
-        {
-            LoRaMacDeviceClass = mibSet->Param.Class;
-            switch( LoRaMacDeviceClass )
-            {
-                case CLASS_A:
-                {
-                    // Set the radio into sleep to setup a defined state
-                    Radio.Sleep( );
-                    break;
-                }
-                case CLASS_B:
-                {
-                    break;
-                }
-                case CLASS_C:
-                {
-                    // Set the NodeAckRequested indicator to default
-                    NodeAckRequested = false;
-                    OnRxWindow2TimerEvent( );
-                    break;
-                }
-            }
-            break;
+      }
+      MacCommandsInNextTx = false;
+      // Store MAC commands which must be re-send in case the device does not
+      // receive a downlink anymore
+      MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat(
+        MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat);
+      if (MacCommandsBufferToRepeatIndex > 0) {
+        MacCommandsInNextTx = true;
+      }
+      MacCommandsBufferIndex = 0;
+
+      if ((payload != NULL) && (payloadSize > 0)) {
+        LoRaMacBuffer[pktHeaderLen++] = framePort;
+
+        if (framePort == 0) {
+          LoRaMacPayloadEncrypt((uint8_t*)payload, payloadSize, LoRaMacNwkSKey, LoRaMacDevAddr,
+                                UP_LINK, UpLinkCounter, LoRaMacPayload);
         }
-        case MIB_NETWORK_JOINED:
-        {
-            IsLoRaMacNetworkJoined = mibSet->Param.IsNetworkJoined;
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-            if( IsLoRaMacNetworkJoined == false )
-            {
-                NextJoinBlock = 0;
-                JoinBlocksRemaining = 0xff;
-                Join500KHzRemaining = 0xff;
-            }
-#endif
-            break;
-        }
-        case MIB_ADR:
-        {
-            AdrCtrlOn = mibSet->Param.AdrEnable;
-            break;
-        }
-        case MIB_NET_ID:
-        {
-            LoRaMacNetID = mibSet->Param.NetID;
-            break;
-        }
-        case MIB_DEV_ADDR:
-        {
-            LoRaMacDevAddr = mibSet->Param.DevAddr;
-            break;
-        }
-        case MIB_NWK_SKEY:
-        {
-            if( mibSet->Param.NwkSKey != NULL )
-            {
-                memcpy1( LoRaMacNwkSKey, mibSet->Param.NwkSKey,
-                               sizeof( LoRaMacNwkSKey ) );
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
+        else {
+          LoRaMacPayloadEncrypt((uint8_t*)payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr,
+                                UP_LINK, UpLinkCounter, LoRaMacPayload);
         }
-        case MIB_APP_SKEY:
-        {
-            if( mibSet->Param.AppSKey != NULL )
-            {
-                memcpy1( LoRaMacAppSKey, mibSet->Param.AppSKey,
-                               sizeof( LoRaMacAppSKey ) );
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_PUBLIC_NETWORK:
-        {
-            SetPublicNetwork( mibSet->Param.EnablePublicNetwork );
-            break;
-        }
-        case MIB_REPEATER_SUPPORT:
-        {
-             RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
-            break;
-        }
-        case MIB_RX2_CHANNEL:
-        {
-            Rx2Channel = mibSet->Param.Rx2Channel;
-            break;
-        }
-        case MIB_CHANNELS_MASK:
-        {
-            if( mibSet->Param.ChannelsMask )
-            {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                bool chanMaskState = true;
-
-#if defined( USE_BAND_915_HYBRID )
-                chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask );
+        memcpy1(LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize);
+      }
+      LoRaMacBufferPktLen = pktHeaderLen + payloadSize;
+
+      LoRaMacComputeMic(LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK,
+                        UpLinkCounter, &mic);
+
+      LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
+      LoRaMacBuffer[LoRaMacBufferPktLen + 1] = (mic >> 8) & 0xFF;
+      LoRaMacBuffer[LoRaMacBufferPktLen + 2] = (mic >> 16) & 0xFF;
+      LoRaMacBuffer[LoRaMacBufferPktLen + 3] = (mic >> 24) & 0xFF;
+
+      LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
+
+      break;
+    case FRAME_TYPE_PROPRIETARY:
+      if ((fBuffer != NULL) && (fBufferSize > 0)) {
+        memcpy1(LoRaMacBuffer + pktHeaderLen, (uint8_t*)fBuffer, fBufferSize);
+        LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
+      }
+      break;
+    default:
+      return LORAMAC_STATUS_SERVICE_UNKNOWN;
+  }
+
+  return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t SendFrameOnChannel(ChannelParams_t channel) {
+  int8_t datarate     = Datarates[ChannelsDatarate];
+  int8_t txPowerIndex = 0;
+  int8_t txPower      = 0;
+
+  txPowerIndex = LimitTxPower(ChannelsTxPower);
+  txPower      = TxPowers[txPowerIndex];
+
+  MlmeConfirm.Status   = LORAMAC_EVENT_INFO_STATUS_ERROR;
+  McpsConfirm.Status   = LORAMAC_EVENT_INFO_STATUS_ERROR;
+  McpsConfirm.Datarate = ChannelsDatarate;
+  McpsConfirm.TxPower  = txPowerIndex;
+
+  Radio.SetChannel(channel.Frequency);
+
+// LOG("Radio TxPower=%u\r\n", txPower);
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+  if (ChannelsDatarate == DR_7) {  // High Speed FSK channel
+    Radio.SetMaxPayloadLength(MODEM_FSK, LoRaMacBufferPktLen);
+    Radio.SetTxConfig(MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false,
+                      3e6);
+    TxTimeOnAir = Radio.TimeOnAir(MODEM_FSK, LoRaMacBufferPktLen);
+  }
+  else if (ChannelsDatarate == DR_6) {  // High speed LoRa channel
+    Radio.SetMaxPayloadLength(MODEM_LORA, LoRaMacBufferPktLen);
+    Radio.SetTxConfig(MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6);
+    TxTimeOnAir = Radio.TimeOnAir(MODEM_LORA, LoRaMacBufferPktLen);
+  }
+  else {  // Normal LoRa channel
+    Radio.SetMaxPayloadLength(MODEM_LORA, LoRaMacBufferPktLen);
+    Radio.SetTxConfig(MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6);
+    TxTimeOnAir = Radio.TimeOnAir(MODEM_LORA, LoRaMacBufferPktLen);
+  }
+#elif defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+  Radio.SetMaxPayloadLength(MODEM_LORA, LoRaMacBufferPktLen);
+  if (ChannelsDatarate >= DR_4) {  // High speed LoRa channel BW500 kHz
+    Radio.SetTxConfig(MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6);
+    TxTimeOnAir = Radio.TimeOnAir(MODEM_LORA, LoRaMacBufferPktLen);
+  }
+  else {  // Normal LoRa channel
+    Radio.SetTxConfig(MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6);
+    TxTimeOnAir = Radio.TimeOnAir(MODEM_LORA, LoRaMacBufferPktLen);
+  }
+#else
+#error "Please define a frequency band in the compiler options."
+#endif
+
+  // Store the time on air
+  McpsConfirm.TxTimeOnAir = TxTimeOnAir;
+  MlmeConfirm.TxTimeOnAir = TxTimeOnAir;
+
+  // Starts the MAC layer status check timer
+  TimerSetValue(&MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT);
+  TimerStart(&MacStateCheckTimer);
+
+  // Send now
+  Radio.Send(LoRaMacBuffer, LoRaMacBufferPktLen);
+
+  LoRaMacState |= MAC_TX_RUNNING;
+
+  return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t LoRaMacInitialization(LoRaMacPrimitives_t* primitives,
+                                      LoRaMacCallback_t*   callbacks) {
+  if (primitives == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+
+  if ((primitives->MacMcpsConfirm == NULL) || (primitives->MacMcpsIndication == NULL) ||
+      (primitives->MacMlmeConfirm == NULL)) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+
+  LoRaMacPrimitives = primitives;
+  LoRaMacCallbacks  = callbacks;
+
+  LoRaMacFlags.Value = 0;
+
+  LoRaMacDeviceClass = CLASS_A;
+
+  UpLinkCounter   = 1;
+  DownLinkCounter = 0;
+  AdrAckCounter   = 0;
+
+  ChannelsNbRepCounter = 0;
+
+  AckTimeoutRetries        = 1;
+  AckTimeoutRetriesCounter = 1;
+  AckTimeoutRetry          = false;
+
+  MaxDCycle        = 0;
+  AggregatedDCycle = 1;
+
+  MacCommandsBufferIndex         = 0;
+  MacCommandsBufferToRepeatIndex = 0;
+
+  IsRxWindowsEnabled = true;
+
+  RepeaterSupport        = false;
+  IsRxWindowsEnabled     = true;
+  IsLoRaMacNetworkJoined = false;
+  LoRaMacState           = MAC_IDLE;
+
+  NodeAckRequested    = false;
+  SrvAckRequested     = false;
+  MacCommandsInNextTx = false;
+
+#if defined(USE_BAND_433)
+  ChannelsMask[0] = LC(1) + LC(2) + LC(3);
+#elif defined(USE_BAND_780)
+  ChannelsMask[0] = LC(1) + LC(2) + LC(3);
+#elif defined(USE_BAND_868)
+  ChannelsMask[0] = LC(1) + LC(2) + LC(3);
+#elif defined(USE_BAND_915)
+  ChannelsMask[0] = 0xFFFF;
+  ChannelsMask[1] = 0xFFFF;
+  ChannelsMask[2] = 0xFFFF;
+  ChannelsMask[3] = 0xFFFF;
+  ChannelsMask[4] = 0x00FF;
+  ChannelsMask[5] = 0x0000;
+
+  memcpy1((uint8_t*)ChannelsMaskRemaining, (uint8_t*)ChannelsMask, sizeof(ChannelsMask));
+#elif defined(USE_BAND_915_HYBRID)
+  ChannelsMask[0] = 0x00FF;
+  ChannelsMask[1] = 0x0000;
+  ChannelsMask[2] = 0x0000;
+  ChannelsMask[3] = 0x0000;
+  ChannelsMask[4] = 0x0001;
+  ChannelsMask[5] = 0x0000;
+
+  memcpy1((uint8_t*)ChannelsMaskRemaining, (uint8_t*)ChannelsMask, sizeof(ChannelsMask));
+#else
+#error "Please define a frequency band in the compiler options."
+#endif
+
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+  // 125 kHz channels
+  for (uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++) {
+    Channels[i].Frequency     = 902.3e6 + i * 200e3;
+    Channels[i].DrRange.Value = (DR_3 << 4) | DR_0;
+    Channels[i].Band          = 0;
+  }
+  // 500 kHz channels
+  for (uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++) {
+    Channels[i].Frequency     = 903.0e6 + (i - (LORA_MAX_NB_CHANNELS - 8)) * 1.6e6;
+    Channels[i].DrRange.Value = (DR_4 << 4) | DR_4;
+    Channels[i].Band          = 0;
+  }
+#endif
+
+  ChannelsTxPower         = LORAMAC_DEFAULT_TX_POWER;
+  ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
+  ChannelsNbRep                              = 1;
+  ChannelsNbRepCounter                       = 0;
+
+  Rx2Channel.Frequency = 923300000;
+  Rx2Channel.Datarate  = DR_8;
+  Rx1DrOffset          = 0;
+
+  MaxDCycle                = 0;
+  AggregatedDCycle         = 1;
+  AggregatedLastTxDoneTime = 0;
+  AggregatedTimeOff        = 0;
+
+#if defined(USE_BAND_433)
+  DutyCycleOn = false;
+#elif defined(USE_BAND_780)
+  DutyCycleOn     = false;
+#elif defined(USE_BAND_868)
+  DutyCycleOn     = true;
+#elif defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+  DutyCycleOn = false;
+#else
+#error "Please define a frequency band in the compiler options."
 #endif
-                if( chanMaskState == true )
-                {
-                    if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < HYBRD_CHNLS_MIN ) &&
-                        ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
-                    {
-                        status = LORAMAC_STATUS_PARAMETER_INVALID;
-                    }
-                    else
-                    {
-                        memcpy1( ( uint8_t* ) ChannelsMask,
-                                 ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( ChannelsMask ) );
-                        for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ )
-                        {
-                            // Disable channels which are no longer available
-                            ChannelsMaskRemaining[i] &= ChannelsMask[i];
-                        }
-                    }
-                }
-                else
-                {
-                    status = LORAMAC_STATUS_PARAMETER_INVALID;
-                }
-#else
-                memcpy1( ( uint8_t* ) ChannelsMask,
-                         ( uint8_t* ) mibSet->Param.ChannelsMask, 2 );
+
+  MaxRxWindow      = MAX_RX_WINDOW;
+  ReceiveDelay1    = RECEIVE_DELAY1;
+  ReceiveDelay2    = RECEIVE_DELAY2;
+  JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
+  JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
+
+#if defined(USE_BAND_915)
+  NextJoinBlock       = 0;
+  LastJoinBlock       = -1;
+  JoinBlocksRemaining = 0xff;
+  Join500KHzRemaining = 0xff;
 #endif
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_CHANNELS_NB_REP:
-        {
-            if( ( mibSet->Param.ChannelNbRep >= 1 ) &&
-                ( mibSet->Param.ChannelNbRep <= 15 ) )
-            {
-                ChannelsNbRep = mibSet->Param.ChannelNbRep;
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_MAX_RX_WINDOW_DURATION:
-        {
-            MaxRxWindow = mibSet->Param.MaxRxWindow;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_1:
-        {
-            ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_2:
-        {
-            ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_1:
-        {
-            JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_2:
-        {
-            JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
-            break;
+
+  LastJoinTxTime   = 0;
+  JoinAggTimeOnAir = 0;
+
+  TimerInit(&MacStateCheckTimer, OnMacStateCheckTimerEvent);
+  TimerSetValue(&MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT);
+
+  TimerInit(&TxDelayedTimer, OnTxDelayedTimerEvent);
+  TimerInit(&RxWindowTimer1, OnRxWindow1TimerEvent);
+  TimerInit(&RxWindowTimer2, OnRxWindow2TimerEvent);
+  TimerInit(&AckTimeoutTimer, OnAckTimeoutTimerEvent);
+
+  // Initialize Radio driver
+  RadioEvents.TxDone    = OnRadioTxDone;
+  RadioEvents.RxDone    = OnRadioRxDone;
+  RadioEvents.RxError   = OnRadioRxError;
+  RadioEvents.TxTimeout = OnRadioTxTimeout;
+  RadioEvents.RxTimeout = OnRadioRxTimeout;
+  Radio.Init(&RadioEvents);
+
+  // Random seed initialization
+  srand1(Radio.Random());
+
+  // Initialize channel index.
+  Channel = LORA_MAX_NB_CHANNELS;
+
+  PublicNetwork = true;
+  SetPublicNetwork(PublicNetwork);
+  Radio.Sleep();
+
+  return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t LoRaMacQueryTxPossible(uint8_t size, LoRaMacTxInfo_t* txInfo) {
+  int8_t  datarate = ChannelsDefaultDatarate;
+  uint8_t fOptLen  = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
+
+  if (txInfo == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+
+  AdrNextDr(AdrCtrlOn, false, &datarate, NULL);
+
+  if (RepeaterSupport == true) {
+    txInfo->CurrentPayloadSize = MaxPayloadOfDatarateRepeater[datarate];
+  }
+  else {
+    txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
+  }
+
+  if (txInfo->CurrentPayloadSize >= fOptLen) {
+    txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
+  }
+  else {
+    return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
+  }
+
+  if (ValidatePayloadLength(size, datarate, 0) == false) {
+    return LORAMAC_STATUS_LENGTH_ERROR;
+  }
+
+  if (ValidatePayloadLength(size, datarate, fOptLen) == false) {
+    return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
+  }
+
+  return LORAMAC_STATUS_OK;
+}
+
+LoRaMacStatus_t LoRaMacMibGetRequestConfirm(MibRequestConfirm_t* mibGet) {
+  LoRaMacStatus_t status = LORAMAC_STATUS_OK;
+
+  if (mibGet == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+
+  switch (mibGet->Type) {
+    case MIB_DEVICE_CLASS: {
+      mibGet->Param.Class = LoRaMacDeviceClass;
+      break;
+    }
+    case MIB_NETWORK_JOINED: {
+      mibGet->Param.IsNetworkJoined = IsLoRaMacNetworkJoined;
+      break;
+    }
+    case MIB_ADR: {
+      mibGet->Param.AdrEnable = AdrCtrlOn;
+      break;
+    }
+    case MIB_NET_ID: {
+      mibGet->Param.NetID = LoRaMacNetID;
+      break;
+    }
+    case MIB_DEV_ADDR: {
+      mibGet->Param.DevAddr = LoRaMacDevAddr;
+      break;
+    }
+    case MIB_NWK_SKEY: {
+      mibGet->Param.NwkSKey = LoRaMacNwkSKey;
+      break;
+    }
+    case MIB_APP_SKEY: {
+      mibGet->Param.AppSKey = LoRaMacAppSKey;
+      break;
+    }
+    case MIB_PUBLIC_NETWORK: {
+      mibGet->Param.EnablePublicNetwork = PublicNetwork;
+      break;
+    }
+    case MIB_REPEATER_SUPPORT: {
+      mibGet->Param.EnableRepeaterSupport = RepeaterSupport;
+      break;
+    }
+    case MIB_CHANNELS: {
+      mibGet->Param.ChannelList = Channels;
+      break;
+    }
+    case MIB_RX2_CHANNEL: {
+      mibGet->Param.Rx2Channel = Rx2Channel;
+      break;
+    }
+    case MIB_CHANNELS_MASK: {
+      mibGet->Param.ChannelsMask = ChannelsMask;
+      break;
+    }
+    case MIB_CHANNELS_NB_REP: {
+      mibGet->Param.ChannelNbRep = ChannelsNbRep;
+      break;
+    }
+    case MIB_MAX_RX_WINDOW_DURATION: {
+      mibGet->Param.MaxRxWindow = MaxRxWindow;
+      break;
+    }
+    case MIB_RECEIVE_DELAY_1: {
+      mibGet->Param.ReceiveDelay1 = ReceiveDelay1;
+      break;
+    }
+    case MIB_RECEIVE_DELAY_2: {
+      mibGet->Param.ReceiveDelay2 = ReceiveDelay2;
+      break;
+    }
+    case MIB_JOIN_ACCEPT_DELAY_1: {
+      mibGet->Param.JoinAcceptDelay1 = JoinAcceptDelay1;
+      break;
+    }
+    case MIB_JOIN_ACCEPT_DELAY_2: {
+      mibGet->Param.JoinAcceptDelay2 = JoinAcceptDelay2;
+      break;
+    }
+    case MIB_CHANNELS_DEFAULT_DATARATE: {
+      mibGet->Param.ChannelsDefaultDatarate = ChannelsDefaultDatarate;
+      break;
+    }
+    case MIB_CHANNELS_DATARATE: {
+      mibGet->Param.ChannelsDatarate = ChannelsDatarate;
+      break;
+    }
+    case MIB_CHANNELS_TX_POWER: {
+      mibGet->Param.ChannelsTxPower = ChannelsTxPower;
+      break;
+    }
+    case MIB_UPLINK_COUNTER: {
+      mibGet->Param.UpLinkCounter = UpLinkCounter;
+      break;
+    }
+    case MIB_DOWNLINK_COUNTER: {
+      mibGet->Param.DownLinkCounter = DownLinkCounter;
+      break;
+    }
+    case MIB_MULTICAST_CHANNEL: {
+      mibGet->Param.MulticastList = MulticastChannels;
+      break;
+    }
+    default:
+      status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+      break;
+  }
+
+  return status;
+}
+
+LoRaMacStatus_t LoRaMacMibSetRequestConfirm(MibRequestConfirm_t* mibSet) {
+  LoRaMacStatus_t status = LORAMAC_STATUS_OK;
+
+  if (mibSet == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  if ((LoRaMacState & MAC_TX_RUNNING) == MAC_TX_RUNNING) {
+    return LORAMAC_STATUS_BUSY;
+  }
+
+  switch (mibSet->Type) {
+    case MIB_DEVICE_CLASS: {
+      LoRaMacDeviceClass = mibSet->Param.Class;
+      switch (LoRaMacDeviceClass) {
+        case CLASS_A: {
+          // Set the radio into sleep to setup a defined state
+          Radio.Sleep();
+          break;
         }
-        case MIB_CHANNELS_DEFAULT_DATARATE:
-        {
-            if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
-                              LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
-            {
-                ChannelsDefaultDatarate = mibSet->Param.ChannelsDefaultDatarate;
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
+        case CLASS_B: {
+          break;
         }
-        case MIB_CHANNELS_DATARATE:
-        {
-            if( ValueInRange( mibSet->Param.ChannelsDatarate,
-                              LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
-            {
-                ChannelsDatarate = mibSet->Param.ChannelsDatarate;
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
+        case CLASS_C: {
+          // Set the NodeAckRequested indicator to default
+          NodeAckRequested = false;
+          OnRxWindow2TimerEvent();
+          break;
         }
-        case MIB_CHANNELS_TX_POWER:
-        {
-            if( ValueInRange( mibSet->Param.ChannelsTxPower,
-                              LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
-            {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                int8_t txPower = LimitTxPower( mibSet->Param.ChannelsTxPower );
-                if( txPower == mibSet->Param.ChannelsTxPower )
-                {
-                    ChannelsTxPower = mibSet->Param.ChannelsTxPower;
-                }
-                else
-                {
-                    status = LORAMAC_STATUS_PARAMETER_INVALID;
-                }
-#else
-                ChannelsTxPower = mibSet->Param.ChannelsTxPower;
+      }
+      break;
+    }
+    case MIB_NETWORK_JOINED: {
+      IsLoRaMacNetworkJoined = mibSet->Param.IsNetworkJoined;
+#if defined(USE_BAND_915)
+      if (IsLoRaMacNetworkJoined == false) {
+        NextJoinBlock       = 0;
+        JoinBlocksRemaining = 0xff;
+        Join500KHzRemaining = 0xff;
+      }
 #endif
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
+      break;
+    }
+    case MIB_ADR: {
+      AdrCtrlOn = mibSet->Param.AdrEnable;
+      break;
+    }
+    case MIB_NET_ID: {
+      LoRaMacNetID = mibSet->Param.NetID;
+      break;
+    }
+    case MIB_DEV_ADDR: {
+      LoRaMacDevAddr = mibSet->Param.DevAddr;
+      break;
+    }
+    case MIB_NWK_SKEY: {
+      if (mibSet->Param.NwkSKey != NULL) {
+        memcpy1(LoRaMacNwkSKey, mibSet->Param.NwkSKey, sizeof(LoRaMacNwkSKey));
+      }
+      else {
+        status = LORAMAC_STATUS_PARAMETER_INVALID;
+      }
+      break;
+    }
+    case MIB_APP_SKEY: {
+      if (mibSet->Param.AppSKey != NULL) {
+        memcpy1(LoRaMacAppSKey, mibSet->Param.AppSKey, sizeof(LoRaMacAppSKey));
+      }
+      else {
+        status = LORAMAC_STATUS_PARAMETER_INVALID;
+      }
+      break;
+    }
+    case MIB_PUBLIC_NETWORK: {
+      SetPublicNetwork(mibSet->Param.EnablePublicNetwork);
+      break;
+    }
+    case MIB_REPEATER_SUPPORT: {
+      RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
+      break;
+    }
+    case MIB_RX2_CHANNEL: {
+      Rx2Channel = mibSet->Param.Rx2Channel;
+      break;
+    }
+    case MIB_CHANNELS_MASK: {
+      if (mibSet->Param.ChannelsMask) {
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+        bool chanMaskState = true;
+
+#if defined(USE_BAND_915_HYBRID)
+        chanMaskState = ValidateChannelMask(mibSet->Param.ChannelsMask);
+#endif
+        if (chanMaskState == true) {
+          if ((CountNbEnabled125kHzChannels(mibSet->Param.ChannelsMask) < HYBRD_CHNLS_MIN) &&
+              (CountNbEnabled125kHzChannels(mibSet->Param.ChannelsMask) > 0)) {
+            status = LORAMAC_STATUS_PARAMETER_INVALID;
+          }
+          else {
+            memcpy1((uint8_t*)ChannelsMask, (uint8_t*)mibSet->Param.ChannelsMask,
+                    sizeof(ChannelsMask));
+            for (uint8_t i = 0; i < sizeof(ChannelsMask) / 2; i++) {
+              // Disable channels which are no longer available
+              ChannelsMaskRemaining[i] &= ChannelsMask[i];
             }
-            break;
+          }
         }
-        case MIB_UPLINK_COUNTER:
-        {
-            UpLinkCounter = mibSet->Param.UpLinkCounter;
-            break;
+        else {
+          status = LORAMAC_STATUS_PARAMETER_INVALID;
         }
-        case MIB_DOWNLINK_COUNTER:
-        {
-            DownLinkCounter = mibSet->Param.DownLinkCounter;
-            break;
-        }
-        default:
-            status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-            break;
+#else
+        memcpy1((uint8_t*)ChannelsMask, (uint8_t*)mibSet->Param.ChannelsMask, 2);
+#endif
+      }
+      else {
+        status = LORAMAC_STATUS_PARAMETER_INVALID;
+      }
+      break;
+    }
+    case MIB_CHANNELS_NB_REP: {
+      if ((mibSet->Param.ChannelNbRep >= 1) && (mibSet->Param.ChannelNbRep <= 15)) {
+        ChannelsNbRep = mibSet->Param.ChannelNbRep;
+      }
+      else {
+        status = LORAMAC_STATUS_PARAMETER_INVALID;
+      }
+      break;
+    }
+    case MIB_MAX_RX_WINDOW_DURATION: {
+      MaxRxWindow = mibSet->Param.MaxRxWindow;
+      break;
+    }
+    case MIB_RECEIVE_DELAY_1: {
+      ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
+      break;
+    }
+    case MIB_RECEIVE_DELAY_2: {
+      ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
+      break;
+    }
+    case MIB_JOIN_ACCEPT_DELAY_1: {
+      JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
+      break;
+    }
+    case MIB_JOIN_ACCEPT_DELAY_2: {
+      JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
+      break;
     }
-
-    return status;
-}
-
-LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
-{
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    return LORAMAC_STATUS_PARAMETER_INVALID;
+    case MIB_CHANNELS_DEFAULT_DATARATE: {
+      if (ValueInRange(mibSet->Param.ChannelsDefaultDatarate, LORAMAC_TX_MIN_DATARATE,
+                       LORAMAC_TX_MAX_DATARATE)) {
+        ChannelsDefaultDatarate = mibSet->Param.ChannelsDefaultDatarate;
+      }
+      else {
+        status = LORAMAC_STATUS_PARAMETER_INVALID;
+      }
+      break;
+    }
+    case MIB_CHANNELS_DATARATE: {
+      if (ValueInRange(mibSet->Param.ChannelsDatarate, LORAMAC_TX_MIN_DATARATE,
+                       LORAMAC_TX_MAX_DATARATE)) {
+        ChannelsDatarate = mibSet->Param.ChannelsDatarate;
+      }
+      else {
+        status = LORAMAC_STATUS_PARAMETER_INVALID;
+      }
+      break;
+    }
+    case MIB_CHANNELS_TX_POWER: {
+      if (ValueInRange(mibSet->Param.ChannelsTxPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER)) {
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+        int8_t txPower = LimitTxPower(mibSet->Param.ChannelsTxPower);
+        if (txPower == mibSet->Param.ChannelsTxPower) {
+          ChannelsTxPower = mibSet->Param.ChannelsTxPower;
+        }
+        else {
+          status = LORAMAC_STATUS_PARAMETER_INVALID;
+        }
 #else
-    bool datarateInvalid = false;
-    bool frequencyInvalid = false;
-    uint8_t band = 0;
-
-    // The id must not exceed LORA_MAX_NB_CHANNELS
-    if( id >= LORA_MAX_NB_CHANNELS )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
+        ChannelsTxPower    = mibSet->Param.ChannelsTxPower;
+#endif
+      }
+      else {
+        status = LORAMAC_STATUS_PARAMETER_INVALID;
+      }
+      break;
     }
-    // Validate if the MAC is in a correct state
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
-        {
-            return LORAMAC_STATUS_BUSY;
-        }
+    case MIB_UPLINK_COUNTER: {
+      UpLinkCounter = mibSet->Param.UpLinkCounter;
+      break;
+    }
+    case MIB_DOWNLINK_COUNTER: {
+      DownLinkCounter = mibSet->Param.DownLinkCounter;
+      break;
     }
-    // Validate the datarate
-    if( ( params.DrRange.Fields.Min > params.DrRange.Fields.Max ) ||
-        ( ValueInRange( params.DrRange.Fields.Min, LORAMAC_TX_MIN_DATARATE,
-                        LORAMAC_TX_MAX_DATARATE ) == false ) ||
-        ( ValueInRange( params.DrRange.Fields.Max, LORAMAC_TX_MIN_DATARATE,
-                        LORAMAC_TX_MAX_DATARATE ) == false ) )
-    {
-        datarateInvalid = true;
+    default:
+      status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+      break;
+  }
+
+  return status;
+}
+
+LoRaMacStatus_t LoRaMacChannelAdd(uint8_t id, ChannelParams_t params) {
+#if (defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+  return LORAMAC_STATUS_PARAMETER_INVALID;
+#else
+  bool    datarateInvalid  = false;
+  bool    frequencyInvalid = false;
+  uint8_t band             = 0;
+
+  // The id must not exceed LORA_MAX_NB_CHANNELS
+  if (id >= LORA_MAX_NB_CHANNELS) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  // Validate if the MAC is in a correct state
+  if ((LoRaMacState & MAC_TX_RUNNING) == MAC_TX_RUNNING) {
+    if ((LoRaMacState & MAC_TX_CONFIG) != MAC_TX_CONFIG) {
+      return LORAMAC_STATUS_BUSY;
     }
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( id < 3 )
-    {
-        if( params.Frequency != Channels[id].Frequency )
-        {
-            frequencyInvalid = true;
-        }
-
-        if( params.DrRange.Fields.Min > ChannelsDefaultDatarate )
-        {
-            datarateInvalid = true;
-        }
-        if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_TX_MAX_DATARATE ) == false )
-        {
-            datarateInvalid = true;
-        }
+  }
+  // Validate the datarate
+  if ((params.DrRange.Fields.Min > params.DrRange.Fields.Max) ||
+      (ValueInRange(params.DrRange.Fields.Min, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE) ==
+       false) ||
+      (ValueInRange(params.DrRange.Fields.Max, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE) ==
+       false)) {
+    datarateInvalid = true;
+  }
+
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+  if (id < 3) {
+    if (params.Frequency != Channels[id].Frequency) {
+      frequencyInvalid = true;
+    }
+
+    if (params.DrRange.Fields.Min > ChannelsDefaultDatarate) {
+      datarateInvalid = true;
+    }
+    if (ValueInRange(params.DrRange.Fields.Max, DR_5, LORAMAC_TX_MAX_DATARATE) == false) {
+      datarateInvalid = true;
+    }
+  }
+#endif
+
+  // Validate the frequency
+  if ((Radio.CheckRfFrequency(params.Frequency) == true) && (params.Frequency > 0) &&
+      (frequencyInvalid == false)) {
+#if defined(USE_BAND_868)
+    if ((params.Frequency >= 865000000) && (params.Frequency <= 868000000)) {
+      band = BAND_G1_0;
+    }
+    else if ((params.Frequency > 868000000) && (params.Frequency <= 868600000)) {
+      band = BAND_G1_1;
+    }
+    else if ((params.Frequency >= 868700000) && (params.Frequency <= 869200000)) {
+      band = BAND_G1_2;
+    }
+    else if ((params.Frequency >= 869400000) && (params.Frequency <= 869650000)) {
+      band = BAND_G1_3;
+    }
+    else if ((params.Frequency >= 869700000) && (params.Frequency <= 870000000)) {
+      band = BAND_G1_4;
+    }
+    else {
+      frequencyInvalid = true;
     }
 #endif
-
-    // Validate the frequency
-    if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) )
-    {
-#if defined( USE_BAND_868 )
-        if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
-        {
-            band = BAND_G1_0;
-        }
-        else if( ( params.Frequency > 868000000 ) && ( params.Frequency <= 868600000 ) )
-        {
-            band = BAND_G1_1;
-        }
-        else if( ( params.Frequency >= 868700000 ) && ( params.Frequency <= 869200000 ) )
-        {
-            band = BAND_G1_2;
-        }
-        else if( ( params.Frequency >= 869400000 ) && ( params.Frequency <= 869650000 ) )
-        {
-            band = BAND_G1_3;
-        }
-        else if( ( params.Frequency >= 869700000 ) && ( params.Frequency <= 870000000 ) )
-        {
-            band = BAND_G1_4;
-        }
-        else
-        {
-            frequencyInvalid = true;
-        }
-#endif
-    }
-    else
-    {
-        frequencyInvalid = true;
-    }
-
-    if( ( datarateInvalid == true ) && ( frequencyInvalid == true ) )
-    {
-        return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
-    }
-    if( datarateInvalid == true )
-    {
-        return LORAMAC_STATUS_DATARATE_INVALID;
-    }
-    if( frequencyInvalid == true )
-    {
-        return LORAMAC_STATUS_FREQUENCY_INVALID;
-    }
-
-    // Every parameter is valid, activate the channel
-    Channels[id] = params;
-    Channels[id].Band = band;
-    ChannelsMask[0] |= ( 1 << id );
-
-    return LORAMAC_STATUS_OK;
+  }
+  else {
+    frequencyInvalid = true;
+  }
+
+  if ((datarateInvalid == true) && (frequencyInvalid == true)) {
+    return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
+  }
+  if (datarateInvalid == true) {
+    return LORAMAC_STATUS_DATARATE_INVALID;
+  }
+  if (frequencyInvalid == true) {
+    return LORAMAC_STATUS_FREQUENCY_INVALID;
+  }
+
+  // Every parameter is valid, activate the channel
+  Channels[id]      = params;
+  Channels[id].Band = band;
+  ChannelsMask[0] |= (1 << id);
+
+  return LORAMAC_STATUS_OK;
 #endif
 }
 
-LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
-{
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
-        {
-            return LORAMAC_STATUS_BUSY;
-        }
-    }
-
-    if( ( id < 3 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
+LoRaMacStatus_t LoRaMacChannelRemove(uint8_t id) {
+#if defined(USE_BAND_433) || defined(USE_BAND_780) || defined(USE_BAND_868)
+  if ((LoRaMacState & MAC_TX_RUNNING) == MAC_TX_RUNNING) {
+    if ((LoRaMacState & MAC_TX_CONFIG) != MAC_TX_CONFIG) {
+      return LORAMAC_STATUS_BUSY;
     }
-    else
-    {
-        // Remove the channel from the list of channels
-        Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 };
-
-        // Disable the channel as it doesn't exist anymore
-        if( DisableChannelInMask( id, ChannelsMask ) == false )
-        {
-            return LORAMAC_STATUS_PARAMETER_INVALID;
-        }
+  }
+
+  if ((id < 3) || (id >= LORA_MAX_NB_CHANNELS)) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  else {
+    // Remove the channel from the list of channels
+    Channels[id] = (ChannelParams_t){0, {0}, 0};
+
+    // Disable the channel as it doesn't exist anymore
+    if (DisableChannelInMask(id, ChannelsMask) == false) {
+      return LORAMAC_STATUS_PARAMETER_INVALID;
     }
-    return LORAMAC_STATUS_OK;
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  return LORAMAC_STATUS_OK;
+#elif (defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID))
+  return LORAMAC_STATUS_PARAMETER_INVALID;
 #endif
 }
 
-LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam )
-{
-    if( channelParam == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    // Reset downlink counter
-    channelParam->DownLinkCounter = 0;
-
-    if( MulticastChannels == NULL )
-    {
-        // New node is the fist element
-        MulticastChannels = channelParam;
+LoRaMacStatus_t LoRaMacMulticastChannelLink(MulticastParams_t* channelParam) {
+  if (channelParam == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  if ((LoRaMacState & MAC_TX_RUNNING) == MAC_TX_RUNNING) {
+    return LORAMAC_STATUS_BUSY;
+  }
+
+  // Reset downlink counter
+  channelParam->DownLinkCounter = 0;
+
+  if (MulticastChannels == NULL) {
+    // New node is the fist element
+    MulticastChannels = channelParam;
+  }
+  else {
+    MulticastParams_t* cur = MulticastChannels;
+
+    // Search the last node in the list
+    while (cur->Next != NULL) {
+      cur = cur->Next;
     }
-    else
-    {
-        MulticastParams_t *cur = MulticastChannels;
-
-        // Search the last node in the list
-        while( cur->Next != NULL )
-        {
-            cur = cur->Next;
-        }
-        // This function always finds the last node
-        cur->Next = channelParam;
-    }
-
-    return LORAMAC_STATUS_OK;
+    // This function always finds the last node
+    cur->Next = channelParam;
+  }
+
+  return LORAMAC_STATUS_OK;
 }
 
-LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam )
-{
-    if( channelParam == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
+LoRaMacStatus_t LoRaMacMulticastChannelUnlink(MulticastParams_t* channelParam) {
+  if (channelParam == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  if ((LoRaMacState & MAC_TX_RUNNING) == MAC_TX_RUNNING) {
+    return LORAMAC_STATUS_BUSY;
+  }
+
+  if (MulticastChannels != NULL) {
+    if (MulticastChannels == channelParam) {
+      // First element
+      MulticastChannels = channelParam->Next;
     }
-
-    if( MulticastChannels != NULL )
-    {
-        if( MulticastChannels == channelParam )
-        {
-          // First element
-          MulticastChannels = channelParam->Next;
-        }
-        else
-        {
-            MulticastParams_t *cur = MulticastChannels;
-
-            // Search the node in the list
-            while( cur->Next && cur->Next != channelParam )
-            {
-                cur = cur->Next;
-            }
-            // If we found the node, remove it
-            if( cur->Next )
-            {
-                cur->Next = channelParam->Next;
-            }
-        }
-        channelParam->Next = NULL;
+    else {
+      MulticastParams_t* cur = MulticastChannels;
+
+      // Search the node in the list
+      while (cur->Next && cur->Next != channelParam) {
+        cur = cur->Next;
+      }
+      // If we found the node, remove it
+      if (cur->Next) {
+        cur->Next = channelParam->Next;
+      }
     }
-
-    return LORAMAC_STATUS_OK;
+    channelParam->Next = NULL;
+  }
+
+  return LORAMAC_STATUS_OK;
 }
 
-LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-    LoRaMacHeader_t macHdr;
-
-    if( mlmeRequest == NULL )
-    {
+LoRaMacStatus_t LoRaMacMlmeRequest(MlmeReq_t* mlmeRequest) {
+  LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+  LoRaMacHeader_t macHdr;
+
+  if (mlmeRequest == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  if ((LoRaMacState & MAC_TX_RUNNING) == MAC_TX_RUNNING) {
+    return LORAMAC_STATUS_BUSY;
+  }
+
+  memset1((uint8_t*)&MlmeConfirm, 0, sizeof(MlmeConfirm));
+
+  MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+
+  switch (mlmeRequest->Type) {
+    case MLME_JOIN: {
+      if ((LoRaMacState & MAC_TX_DELAYED) == MAC_TX_DELAYED) {
+        return LORAMAC_STATUS_BUSY;
+      }
+
+      MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+
+      if ((mlmeRequest->Req.Join.DevEui == NULL) || (mlmeRequest->Req.Join.AppEui == NULL) ||
+          (mlmeRequest->Req.Join.AppKey == NULL)) {
         return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
-
-    MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-
-    switch( mlmeRequest->Type )
-    {
-        case MLME_JOIN:
-        {
-            if( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED )
-            {
-                return LORAMAC_STATUS_BUSY;
-            }
-
-            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
-            if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
-                ( mlmeRequest->Req.Join.AppEui == NULL ) ||
-                ( mlmeRequest->Req.Join.AppKey == NULL ) )
-            {
-                return LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-
-            LoRaMacFlags.Bits.MlmeReq = 1;
-
-            LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
-            LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
-            LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
-
-// Disable join retransmission dutycycle as it does not currently 
-// handle device reset 
+      }
+
+      LoRaMacFlags.Bits.MlmeReq = 1;
+
+      LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
+      LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
+      LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
+
+// Disable join retransmission dutycycle as it does not currently
+// handle device reset
 #if 0
             if( LoRaMacCalcJoinBackOff( ) != 0 )
             {
@@ -4061,243 +3589,213 @@
             }
 #endif
 
-            macHdr.Value = 0;
-            macHdr.Bits.MType  = FRAME_TYPE_JOIN_REQ;
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-            if ( IsLoRaMacNetworkJoined == true )
-            {
-                NextJoinBlock = 0;
-                JoinBlocksRemaining = 0xff;
-                Join500KHzRemaining = 0xff;
-                IsLoRaMacNetworkJoined = false;
-            }
+      macHdr.Value      = 0;
+      macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
+
+#if defined(USE_BAND_915)
+      if (IsLoRaMacNetworkJoined == true) {
+        NextJoinBlock          = 0;
+        JoinBlocksRemaining    = 0xff;
+        Join500KHzRemaining    = 0xff;
+        IsLoRaMacNetworkJoined = false;
+      }
 #endif
 
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-#if defined( USE_BAND_915 )
-            // Re-enable 500 kHz default channels
-            ChannelsMask[4] = 0x00FF;
-#else // defined( USE_BAND_915_HYBRID )
-            // Re-enable 500 kHz default channels
-            ChannelsMask[4] = 0x0001;
+#if defined(USE_BAND_915) || defined(USE_BAND_915_HYBRID)
+#if defined(USE_BAND_915)
+      // Re-enable 500 kHz default channels
+      ChannelsMask[4] = 0x00FF;
+#else  // defined( USE_BAND_915_HYBRID )
+      // Re-enable 500 kHz default channels
+      ChannelsMask[4] = 0x0001;
 #endif
 
-            static uint8_t drSwitch = 0;
-
-            if( ( ++drSwitch & 0x01 ) == 0x01 )
-            {
-                ChannelsDatarate = DR_0;
-            }
-            else
-            {
-                ChannelsDatarate = DR_4;
-            }
+      static uint8_t drSwitch = 0;
+
+      if ((++drSwitch & 0x01) == 0x01) {
+        ChannelsDatarate = DR_0;
+      }
+      else {
+        ChannelsDatarate = DR_4;
+      }
 #endif
 
-            status = Send( &macHdr, 0, NULL, 0 );
-            break;
-        }
-        case MLME_LINK_CHECK:
-        {
-            LoRaMacFlags.Bits.MlmeReq = 1;
-            // LoRaMac will send this command piggy-pack
-            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
-            status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
-            break;
-        }
-        default:
-            break;
+      status = Send(&macHdr, 0, NULL, 0);
+      break;
     }
-
-    if( status != LORAMAC_STATUS_OK )
-    {
-        NodeAckRequested = false;
-        LoRaMacFlags.Bits.MlmeReq = 0;
+    case MLME_LINK_CHECK: {
+      LoRaMacFlags.Bits.MlmeReq = 1;
+      // LoRaMac will send this command piggy-pack
+      MlmeConfirm.MlmeRequest = mlmeRequest->Type;
+
+      status = AddMacCommand(MOTE_MAC_LINK_CHECK_REQ, 0, 0);
+      break;
     }
-
-    return status;
+    default:
+      break;
+  }
+
+  if (status != LORAMAC_STATUS_OK) {
+    NodeAckRequested          = false;
+    LoRaMacFlags.Bits.MlmeReq = 0;
+  }
+
+  return status;
 }
 
-LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-    LoRaMacHeader_t macHdr;
-    uint8_t fPort = 0;
-    void *fBuffer;
-    uint16_t fBufferSize;
-    int8_t datarate;
-    bool readyToSend = false;
-
-    if( mcpsRequest == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
+LoRaMacStatus_t LoRaMacMcpsRequest(McpsReq_t* mcpsRequest) {
+  LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
+  LoRaMacHeader_t macHdr;
+  uint8_t         fPort = 0;
+  void*           fBuffer;
+  uint16_t        fBufferSize;
+  int8_t          datarate;
+  bool            readyToSend = false;
+
+  if (mcpsRequest == NULL) {
+    return LORAMAC_STATUS_PARAMETER_INVALID;
+  }
+  if (((LoRaMacState & MAC_TX_RUNNING) == MAC_TX_RUNNING) ||
+      ((LoRaMacState & MAC_TX_DELAYED) == MAC_TX_DELAYED)) {
+    return LORAMAC_STATUS_BUSY;
+  }
+
+  macHdr.Value = 0;
+  memset1((uint8_t*)&McpsConfirm, 0, sizeof(McpsConfirm));
+  McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
+
+  switch (mcpsRequest->Type) {
+    case MCPS_UNCONFIRMED: {
+      readyToSend              = true;
+      AckTimeoutRetries        = 1;
+      AckTimeoutRetriesCounter = 1;
+
+      macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
+      fPort             = mcpsRequest->Req.Unconfirmed.fPort;
+      fBuffer           = mcpsRequest->Req.Unconfirmed.fBuffer;
+      fBufferSize       = mcpsRequest->Req.Unconfirmed.fBufferSize;
+      datarate          = mcpsRequest->Req.Unconfirmed.Datarate;
+      break;
     }
-    if( ( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) ||
-        ( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED ) )
-    {
-        return LORAMAC_STATUS_BUSY;
+    case MCPS_CONFIRMED: {
+      readyToSend              = true;
+      AckTimeoutRetriesCounter = 1;
+      AckTimeoutRetries        = mcpsRequest->Req.Confirmed.NbTrials;
+
+      macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
+      fPort             = mcpsRequest->Req.Confirmed.fPort;
+      fBuffer           = mcpsRequest->Req.Confirmed.fBuffer;
+      fBufferSize       = mcpsRequest->Req.Confirmed.fBufferSize;
+      datarate          = mcpsRequest->Req.Confirmed.Datarate;
+      break;
     }
-
-    macHdr.Value = 0;
-    memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) );
-    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-
-    switch( mcpsRequest->Type )
-    {
-        case MCPS_UNCONFIRMED:
-        {
-            readyToSend = true;
-            AckTimeoutRetries = 1;
-            AckTimeoutRetriesCounter = 1;
-
-            macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
-            fPort = mcpsRequest->Req.Unconfirmed.fPort;
-            fBuffer = mcpsRequest->Req.Unconfirmed.fBuffer;
-            fBufferSize = mcpsRequest->Req.Unconfirmed.fBufferSize;
-            datarate = mcpsRequest->Req.Unconfirmed.Datarate;
-            break;
-        }
-        case MCPS_CONFIRMED:
-        {
-            readyToSend = true;
-            AckTimeoutRetriesCounter = 1;
-            AckTimeoutRetries = mcpsRequest->Req.Confirmed.NbTrials;
-
-            macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
-            fPort = mcpsRequest->Req.Confirmed.fPort;
-            fBuffer = mcpsRequest->Req.Confirmed.fBuffer;
-            fBufferSize = mcpsRequest->Req.Confirmed.fBufferSize;
-            datarate = mcpsRequest->Req.Confirmed.Datarate;
-            break;
-        }
-        case MCPS_PROPRIETARY:
-        {
-            readyToSend = true;
-            AckTimeoutRetries = 1;
-
-            macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY;
-            fBuffer = mcpsRequest->Req.Proprietary.fBuffer;
-            fBufferSize = mcpsRequest->Req.Proprietary.fBufferSize;
-            datarate = mcpsRequest->Req.Proprietary.Datarate;
-            break;
-        }
-        default:
-            break;
+    case MCPS_PROPRIETARY: {
+      readyToSend       = true;
+      AckTimeoutRetries = 1;
+
+      macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY;
+      fBuffer           = mcpsRequest->Req.Proprietary.fBuffer;
+      fBufferSize       = mcpsRequest->Req.Proprietary.fBufferSize;
+      datarate          = mcpsRequest->Req.Proprietary.Datarate;
+      break;
     }
-
-    if( readyToSend == true )
-    {
-        if( AdrCtrlOn == false )
-        {
-            if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true )
-            {
-                ChannelsDatarate = datarate;
-            }
-            else
-            {
-                return LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-        }
-
-        status = Send( &macHdr, fPort, fBuffer, fBufferSize );
-        if( status == LORAMAC_STATUS_OK )
-        {
-            McpsConfirm.McpsRequest = mcpsRequest->Type;
-            LoRaMacFlags.Bits.McpsReq = 1;
-        }
-        else
-        {
-            NodeAckRequested = false;
-        }
+    default:
+      break;
+  }
+
+  if (readyToSend == true) {
+    if (AdrCtrlOn == false) {
+      if (ValueInRange(datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE) == true) {
+        ChannelsDatarate = datarate;
+      }
+      else {
+        return LORAMAC_STATUS_PARAMETER_INVALID;
+      }
     }
 
-    return status;
+    status = Send(&macHdr, fPort, fBuffer, fBufferSize);
+    if (status == LORAMAC_STATUS_OK) {
+      McpsConfirm.McpsRequest   = mcpsRequest->Type;
+      LoRaMacFlags.Bits.McpsReq = 1;
+    }
+    else {
+      NodeAckRequested = false;
+    }
+  }
+
+  return status;
 }
 
-TimerTime_t LoRaMacCalcJoinBackOff( )
-{
-    TimerTime_t timeOff = 0; 
-    TimerTime_t uptime; 
-    TimerTime_t currDCycleEndTime;
-    TimerTime_t prevDCycleEndTime; 
-    TimerTime_t period;
-    TimerTime_t onAirTimeMax;
-    TimerTime_t lastJoinTime;
-    TimerTime_t elapsedTime;
-    uint8_t     dcyclePeriod;
-
-    // Check retransmit duty-cycle is enabled 
-    if ( JOIN_NB_RETRANSMISSION_DCYCLES == 0 )
-        return 0;
-
-    // Normalize system time values to seconds
-    uptime = TimerGetCurrentTime( ) / 1e6;
-    lastJoinTime = LastJoinTxTime / 1e6;
-
-    // Get dutycycle for current time
-    prevDCycleEndTime = 0;
-    currDCycleEndTime = 0;
-    for(dcyclePeriod = 0; dcyclePeriod < JOIN_NB_RETRANSMISSION_DCYCLES; dcyclePeriod++)
-    {                
-        prevDCycleEndTime  = currDCycleEndTime;
-        currDCycleEndTime += JoinReTransmitDCycle[dcyclePeriod].period;  
-
-        bool isCurrentPeriod = uptime < currDCycleEndTime;
-
-        if( isCurrentPeriod || ( dcyclePeriod == ( JOIN_NB_RETRANSMISSION_DCYCLES-1 ) ) )
-        {
-            period = JoinReTransmitDCycle[dcyclePeriod].period;
-            onAirTimeMax = JoinReTransmitDCycle[dcyclePeriod].onAirTimeMax;
-            if( isCurrentPeriod == true ) 
-                break;
-        }
+TimerTime_t LoRaMacCalcJoinBackOff() {
+  TimerTime_t timeOff = 0;
+  TimerTime_t uptime;
+  TimerTime_t currDCycleEndTime;
+  TimerTime_t prevDCycleEndTime;
+  TimerTime_t period;
+  TimerTime_t onAirTimeMax;
+  TimerTime_t lastJoinTime;
+  TimerTime_t elapsedTime;
+  uint8_t     dcyclePeriod;
+
+  // Check retransmit duty-cycle is enabled
+  if (JOIN_NB_RETRANSMISSION_DCYCLES == 0)
+    return 0;
+
+  // Normalize system time values to seconds
+  uptime       = TimerGetCurrentTime() / 1e6;
+  lastJoinTime = LastJoinTxTime / 1e6;
+
+  // Get dutycycle for current time
+  prevDCycleEndTime = 0;
+  currDCycleEndTime = 0;
+  for (dcyclePeriod = 0; dcyclePeriod < JOIN_NB_RETRANSMISSION_DCYCLES; dcyclePeriod++) {
+    prevDCycleEndTime = currDCycleEndTime;
+    currDCycleEndTime += JoinReTransmitDCycle[dcyclePeriod].period;
+
+    bool isCurrentPeriod = uptime < currDCycleEndTime;
+
+    if (isCurrentPeriod || (dcyclePeriod == (JOIN_NB_RETRANSMISSION_DCYCLES - 1))) {
+      period       = JoinReTransmitDCycle[dcyclePeriod].period;
+      onAirTimeMax = JoinReTransmitDCycle[dcyclePeriod].onAirTimeMax;
+      if (isCurrentPeriod == true)
+        break;
     }
-
-    // Clear aggregate on air time if dutycycle period of last join has elapsed 
-    if( lastJoinTime < prevDCycleEndTime ) 
-    {
+  }
+
+  // Clear aggregate on air time if dutycycle period of last join has elapsed
+  if (lastJoinTime < prevDCycleEndTime) {
+    JoinAggTimeOnAir = 0;
+  }
+  else {
+    elapsedTime = (uptime - prevDCycleEndTime) % period;
+
+    if (dcyclePeriod == JOIN_NB_RETRANSMISSION_DCYCLES) {
+      if (((uptime - prevDCycleEndTime) / period) > ((lastJoinTime - prevDCycleEndTime) / period)) {
         JoinAggTimeOnAir = 0;
-    }
-    else 
-    {
-        elapsedTime = ( uptime - prevDCycleEndTime ) % period;
-        
-        if( dcyclePeriod == JOIN_NB_RETRANSMISSION_DCYCLES )
-        {
-            if( ( ( uptime - prevDCycleEndTime ) / period ) > ( ( lastJoinTime - prevDCycleEndTime ) / period ) )
-            {
-                JoinAggTimeOnAir = 0;
-            }
-        }
-    }
-
-    if ( JoinAggTimeOnAir >= onAirTimeMax ) 
-    {
-        // time off is remaining time until beginning of next period 
-        timeOff = ( period - elapsedTime ); 
+      }
     }
-
-
-    if(timeOff > JOIN_RETRANSMISSION_DC_WAIT_MAX)
-    	timeOff = JOIN_RETRANSMISSION_DC_WAIT_MAX;
-
-    return ( timeOff * 1e6 );
-}
-
-void LoRaMacTestRxWindowsOn( bool enable )
-{
-    IsRxWindowsEnabled = enable;
+  }
+
+  if (JoinAggTimeOnAir >= onAirTimeMax) {
+    // time off is remaining time until beginning of next period
+    timeOff = (period - elapsedTime);
+  }
+
+  if (timeOff > JOIN_RETRANSMISSION_DC_WAIT_MAX)
+    timeOff = JOIN_RETRANSMISSION_DC_WAIT_MAX;
+
+  return (timeOff * 1e6);
 }
 
-void LoRaMacTestSetMic( uint16_t txPacketCounter )
-{
-    UpLinkCounter = txPacketCounter;
-    IsUpLinkCounterFixed = true;
+void LoRaMacTestRxWindowsOn(bool enable) {
+  IsRxWindowsEnabled = enable;
 }
 
-void LoRaMacTestSetDutyCycleOn( bool enable )
-{
-    DutyCycleOn = enable;
+void LoRaMacTestSetMic(uint16_t txPacketCounter) {
+  UpLinkCounter        = txPacketCounter;
+  IsUpLinkCounterFixed = true;
 }
+
+void LoRaMacTestSetDutyCycleOn(bool enable) {
+  DutyCycleOn = enable;
+}
diff -r fc9baa35ae1a -r 8b9e6442a02a LoRaMac.cpp.orig
--- a/LoRaMac.cpp.orig	Tue Aug 08 11:21:18 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4309 +0,0 @@
-/*
- / _____)             _              | |
-( (____  _____ ____ _| |_ _____  ____| |__
- \____ \| ___ |    (_   _) ___ |/ ___)  _ \
- _____) ) ____| | | || |_| ____( (___| | | |
-(______/|_____)_|_|_| \__)_____)\____)_| |_|
-    (C)2013 Semtech
- ___ _____ _   ___ _  _____ ___  ___  ___ ___
-/ __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
-\__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
-|___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
-embedded.connectivity.solutions===============
-
-Description: LoRa MAC layer implementation
-
-License: Revised BSD License, see LICENSE.TXT file include in the project
-
-Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE )
-*/
-#include "board.h"
-
-#include "LoRaMacCrypto.h"
-#include "LoRaMac.h"
-#include "LoRaMacTest.h"
-
-/*!
- * Maximum PHY layer payload size
- */
-#define LORAMAC_PHY_MAXPAYLOAD                      255
-
-/*!
- * Maximum MAC commands buffer size
- */
-#define LORA_MAC_COMMAND_MAX_LENGTH                 15
-
-/*!
- * FRMPayload overhead to be used when setting the Radio.SetMaxPayloadLength
- * in RxWindowSetup function.
- * Maximum PHYPayload = MaxPayloadOfDatarate/MaxPayloadOfDatarateRepeater + LORA_MAC_FRMPAYLOAD_OVERHEAD
- */
-#define LORA_MAC_FRMPAYLOAD_OVERHEAD                13 // MHDR(1) + FHDR(7) + Port(1) + MIC(4)
-
-/*!
- * Minimum number of available channels in Frequency Hopping Mode
- */
-#define FRQ_HOP_CHNLS_MIN 50
-
-/*!
- * Minimum number of available channels in Hybrid Mode
- */
-#define HYBRD_CHNLS_MIN 4
-
-
-/*!
- * Device IEEE EUI
- */
-static uint8_t *LoRaMacDevEui;
-
-/*!
- * Application IEEE EUI
- */
-static uint8_t *LoRaMacAppEui;
-
-/*!
- * AES encryption/decryption cipher application key
- */
-static uint8_t *LoRaMacAppKey;
-
-/*!
- * AES encryption/decryption cipher network session key
- */
-static uint8_t LoRaMacNwkSKey[] =
-{
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/*!
- * AES encryption/decryption cipher application session key
- */
-static uint8_t LoRaMacAppSKey[] =
-{
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/*!
- * Device nonce is a random value extracted by issuing a sequence of RSSI
- * measurements
- */
-static uint16_t LoRaMacDevNonce;
-
-/*!
- * Network ID ( 3 bytes )
- */
-static uint32_t LoRaMacNetID;
-
-/*!
- * Mote Address
- */
-static uint32_t LoRaMacDevAddr;
-
-/*!
- * Multicast channels linked list
- */
-static MulticastParams_t *MulticastChannels = NULL;
-
-/*!
- * Actual device class
- */
-static DeviceClass_t LoRaMacDeviceClass;
-
-/*!
- * Indicates if the node is connected to a private or public network
- */
-static bool PublicNetwork;
-
-/*!
- * Indicates if the node supports repeaters
- */
-static bool RepeaterSupport;
-
-/*!
- * Buffer containing the data to be sent or received.
- */
-static uint8_t LoRaMacBuffer[LORAMAC_PHY_MAXPAYLOAD];
-
-/*!
- * Length of packet in LoRaMacBuffer
- */
-static uint16_t LoRaMacBufferPktLen = 0;
-
-/*!
- * Buffer containing the upper layer data.
- */
-static uint8_t LoRaMacPayload[LORAMAC_PHY_MAXPAYLOAD];
-static uint8_t LoRaMacRxPayload[LORAMAC_PHY_MAXPAYLOAD];
-
-/*!
- * LoRaMAC frame counter. Each time a packet is sent the counter is incremented.
- * Only the 16 LSB bits are sent
- */
-static uint32_t UpLinkCounter = 1;
-
-/*!
- * LoRaMAC frame counter. Each time a packet is received the counter is incremented.
- * Only the 16 LSB bits are received
- */
-static uint32_t DownLinkCounter = 0;
-
-/*!
- * IsPacketCounterFixed enables the MIC field tests by fixing the
- * UpLinkCounter value
- */
-static bool IsUpLinkCounterFixed = false;
-
-/*!
- * Used for test purposes. Disables the opening of the reception windows.
- */
-static bool IsRxWindowsEnabled = true;
-
-/*!
- * Indicates if the MAC layer has already joined a network.
- */
-static bool IsLoRaMacNetworkJoined = false;
-
-/*!
- * LoRaMac ADR control status
- */
-static bool AdrCtrlOn = true;
-
-/*!
- * Counts the number of missed ADR acknowledgements
- */
-static uint32_t AdrAckCounter = 0;
-
-/*!
- * If the node has sent a FRAME_TYPE_DATA_CONFIRMED_UP this variable indicates
- * if the nodes needs to manage the server acknowledgement.
- */
-static bool NodeAckRequested = false;
-
-/*!
- * If the server has sent a FRAME_TYPE_DATA_CONFIRMED_DOWN this variable indicates
- * if the ACK bit must be set for the next transmission
- */
-static bool SrvAckRequested = false;
-
-/*!
- * Indicates if the MAC layer wants to send MAC commands
- */
-static bool MacCommandsInNextTx = false;
-
-/*!
- * Contains the current MacCommandsBuffer index
- */
-static uint8_t MacCommandsBufferIndex = 0;
-
-/*!
- * Contains the current MacCommandsBuffer index for MAC commands to repeat
- */
-static uint8_t MacCommandsBufferToRepeatIndex = 0;
-
-/*!
- * Buffer containing the MAC layer commands
- */
-static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
-
-/*!
- * Buffer containing the MAC layer commands which must be repeated
- */
-static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
-
-#if defined( USE_BAND_433 )
-/*!
- * Data rates table definition
- */
-const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
-
-/*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
-
-/*!
- * Tx output powers table definition
- */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
-    LC1,
-    LC2,
-    LC3,
-};
-#elif defined( USE_BAND_780 )
-/*!
- * Data rates table definition
- */
-const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
-
-/*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarate[] = { 59, 59, 59, 123, 250, 250, 250, 250 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 59, 59, 59, 123, 230, 230, 230, 230 };
-
-/*!
- * Tx output powers table definition
- */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
-    LC1,
-    LC2,
-    LC3,
-};
-#elif defined( USE_BAND_868 )
-/*!
- * Data rates table definition
- */
-const uint8_t Datarates[]  = { 12, 11, 10,  9,  8,  7,  7, 50 };
-
-/*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarate[] = { 51, 51, 51, 115, 242, 242, 242, 242 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 51, 51, 51, 115, 222, 222, 222, 222 };
-
-/*!
- * Tx output powers table definition
- */
-const int8_t TxPowers[]    = { 20, 14, 11,  8,  5,  2 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
-    BAND1,
-    BAND2,
-    BAND3,
-    BAND4,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS] =
-{
-    LC1,
-    LC2,
-    LC3,
-};
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-/*!
- * Data rates table definition
- */
-const uint8_t Datarates[]  = { 10, 9, 8,  7,  8,  0,  0, 0, 12, 11, 10, 9, 8, 7, 0, 0 };
-
-/*!
- * Up/Down link data rates offset definition
- */
-const uint8_t datarateOffsets[16][4] =
-{
-    { DR_10, DR_9 , DR_8 , DR_8  }, // DR_0
-    { DR_11, DR_10, DR_9 , DR_8  }, // DR_1
-    { DR_12, DR_11, DR_10, DR_9  }, // DR_2
-    { DR_13, DR_12, DR_11, DR_10 }, // DR_3
-    { DR_13, DR_13, DR_12, DR_11 }, // DR_4
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { DR_8 , DR_8 , DR_8 , DR_8  },
-    { DR_9 , DR_8 , DR_8 , DR_8  },
-    { DR_10, DR_9 , DR_8 , DR_8  },
-    { DR_11, DR_10, DR_9 , DR_8  },
-    { DR_12, DR_11, DR_10, DR_9  },
-    { DR_13, DR_12, DR_11, DR_10 },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-    { 0xFF , 0xFF , 0xFF , 0xFF  },
-};
-
-/*!
- * Maximum payload with respect to the datarate index. Cannot operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarate[] = { 11, 53, 126, 242, 242, 0, 0, 0, 53, 129, 242, 242, 242, 242, 0, 0 };
-
-/*!
- * Maximum payload with respect to the datarate index. Can operate with repeater.
- */
-const uint8_t MaxPayloadOfDatarateRepeater[] = { 11, 53, 126, 242, 242, 0, 0, 0, 33, 109, 222, 222, 222, 222, 0, 0 };
-
-/*!
- * Tx output powers table definition
- */
-const int8_t TxPowers[]    = { 30, 28, 26, 24, 22, 20, 18, 16, 14, 12, 10 };
-
-/*!
- * LoRaMac bands
- */
-static Band_t Bands[LORA_MAX_NB_BANDS] =
-{
-    BAND0,
-};
-
-/*!
- * LoRaMAC channels
- */
-static ChannelParams_t Channels[LORA_MAX_NB_CHANNELS];
-
-/*!
- * Contains the channels which remain to be applied.
- */
-static uint16_t ChannelsMaskRemaining[6];
-
-#if defined( USE_BAND_915 ) 
-/*!
- *  Last join request sub-band 
- */
-static int8_t LastJoinBlock;
-
-/*!
- * Next join sub-band block
- */
-static uint8_t  NextJoinBlock;
-
-/*!
- * Mask of 125 KHz sub-bands not used for join transmit 
- */
-static uint8_t  JoinBlocksRemaining;
-
-/*!
- * Mask of 500 KHz sub-bands not used for join transmit 
- */
-static uint8_t  Join500KHzRemaining;
-
-#ifndef JOIN_BLOCK_ORDER
-#define JOIN_BLOCK_ORDER { -1, -1, -1, -1, -1, -1, -1, -1 }
-#endif
-
-/*!
- * join sub-band block order 
- */
-static int8_t JoinBlock[8] = JOIN_BLOCK_ORDER;
-
-#endif
-
-/*!
- * Defines the first channel for RX window 2 for US band
- */
-#define LORAMAC_FIRST_RX2_CHANNEL           ( (uint32_t) 923.3e6 )
-
-/*!
- * Defines the last channel for RX window 2 for US band
- */
-#define LORAMAC_LAST_RX2_CHANNEL            ( (uint32_t) 927.5e6 )
-
-/*!
- * Defines the step width of the channels for RX window 2
- */
-#define LORAMAC_STEPWIDTH_RX2_CHANNEL       ( (uint32_t) 600e3 )
-
-
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-
-/*!
- * LoRaMAC 2nd reception window settings
- */
-static Rx2ChannelParams_t Rx2Channel = RX_WND_2_CHANNEL;
-
-/*!
- * Datarate offset between uplink and downlink on first window
- */
-static uint8_t Rx1DrOffset = 0;
-
-/*!
- * Mask indicating which channels are enabled
- */
-static uint16_t ChannelsMask[6];
-
-/*!
- * Channels Tx output power
- */
-static int8_t ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
-
-/*!
- * Channels datarate
- */
-static int8_t ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
-
-/*!
- * Channels default datarate
- */
-static int8_t ChannelsDefaultDatarate = LORAMAC_DEFAULT_DATARATE;
-
-/*!
- * Number of uplink messages repetitions [1:15] (unconfirmed messages only)
- */
-static uint8_t ChannelsNbRep = 1;
-
-/*!
- * Uplink messages repetitions counter
- */
-static uint8_t ChannelsNbRepCounter = 0;
-
-/*!
- * Maximum duty cycle
- * \remark Possibility to shutdown the device.
- */
-static uint8_t MaxDCycle = 0;
-
-/*!
- * Aggregated duty cycle management
- */
-static uint16_t AggregatedDCycle;
-static TimerTime_t AggregatedLastTxDoneTime;
-static TimerTime_t AggregatedTimeOff;
-
-/*!
- * Enables/Disables duty cycle management (Test only)
- */
-static bool DutyCycleOn;
-
-/*!
- * Current channel index
- */
-static uint8_t Channel;
-
-static uint8_t LastTxChannel;
-
-/*!
- * LoRaMac internal states
- */
-enum eLoRaMacState
-{
-    MAC_IDLE          = 0x00000000,
-    MAC_TX_RUNNING    = 0x00000001,
-    MAC_RX            = 0x00000002,
-    MAC_ACK_REQ       = 0x00000004,
-    MAC_ACK_RETRY     = 0x00000008,
-    MAC_TX_DELAYED    = 0x00000010,
-    MAC_TX_CONFIG     = 0x00000020,
-    MAC_RX_ABORT      = 0x00000040,
-};
-
-/*!
- * LoRaMac internal state
- */
-uint32_t LoRaMacState = MAC_IDLE;
-
-/*!
- * LoRaMac timer used to check the LoRaMacState (runs every second)
- */
-static TimerEvent_t MacStateCheckTimer;
-
-/*!
- * LoRaMac upper layer event functions
- */
-static LoRaMacPrimitives_t *LoRaMacPrimitives;
-
-/*!
- * LoRaMac upper layer callback functions
- */
-static LoRaMacCallback_t *LoRaMacCallbacks;
-
-/*!
- * Radio events function pointer
- */
-static RadioEvents_t RadioEvents;
-
-/*!
- * LoRaMac duty cycle delayed Tx timer
- */
-static TimerEvent_t TxDelayedTimer;
-
-/*!
- * LoRaMac reception windows timers
- */
-static TimerEvent_t RxWindowTimer1;
-static TimerEvent_t RxWindowTimer2;
-
-/*!
- * LoRaMac reception windows delay from end of Tx
- */
-static uint32_t ReceiveDelay1;
-static uint32_t ReceiveDelay2;
-static uint32_t JoinAcceptDelay1;
-static uint32_t JoinAcceptDelay2;
-
-/*!
- * LoRaMac reception windows delay
- * \remark normal frame: RxWindowXDelay = ReceiveDelayX - RADIO_WAKEUP_TIME
- *         join frame  : RxWindowXDelay = JoinAcceptDelayX - RADIO_WAKEUP_TIME
- */
-static uint32_t RxWindow1Delay;
-static uint32_t RxWindow2Delay;
-
-/*!
- * LoRaMac maximum time a reception window stays open
- */
-static uint32_t MaxRxWindow;
-
-/*!
- * Acknowledge timeout timer. Used for packet retransmissions.
- */
-static TimerEvent_t AckTimeoutTimer;
-
-/*!
- * Number of trials to get a frame acknowledged
- */
-static uint8_t AckTimeoutRetries = 1;
-
-/*!
- * Number of trials to get a frame acknowledged
- */
-static uint8_t AckTimeoutRetriesCounter = 1;
-
-/*!
- * Indicates if the AckTimeout timer has expired or not
- */
-static bool AckTimeoutRetry = false;
-
-/*!
- * Last transmission time on air
- */
-TimerTime_t TxTimeOnAir = 0;
-
-/*!
- * Structure to hold an MCPS indication data.
- */
-static McpsIndication_t McpsIndication;
-
-/*!
- * Structure to hold MCPS confirm data.
- */
-static McpsConfirm_t McpsConfirm;
-
-/*!
- * Structure to hold MLME confirm data.
- */
-static MlmeConfirm_t MlmeConfirm;
-
-/*!
- * Holds the current rx window slot
- */
-static uint8_t RxSlot = 0;
-
-/*!
- * LoRaMac tx/rx operation state
- */
-LoRaMacFlags_t LoRaMacFlags;
-
-/*!
- * Join Retransmission back-off configuration
- */
-LoRaMacRetransmissionDCycle_t JoinReTransmitDCycle[JOIN_NB_RETRANSMISSION_DCYCLES] = 
-{
-    JOIN_RETRANSMISSION_DCYCLE1, 
-    JOIN_RETRANSMISSION_DCYCLE2, 
-    JOIN_RETRANSMISSION_DCYCLE3
-};
-
-/*!
- * Uptime of the last sent join request
- */
-static TimerTime_t LastJoinTxTime;
-
-/*!
- * Aggregated join request time on air 
- */
-static TimerTime_t JoinAggTimeOnAir; 
-
-
-/*!
- * \brief Function to be executed on Radio Tx Done event
- */
-static void OnRadioTxDone( void );
-
-/*!
- * \brief This function prepares the MAC to abort the execution of function
- *        OnRadioRxDone in case of a reception error.
- */
-static void PrepareRxDoneAbort( void );
-
-/*!
- * \brief Function to be executed on Radio Rx Done event
- */
-static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr );
-
-/*!
- * \brief Function executed on Radio Tx Timeout event
- */
-static void OnRadioTxTimeout( void );
-
-/*!
- * \brief Function executed on Radio Rx error event
- */
-static void OnRadioRxError( void );
-
-/*!
- * \brief Function executed on Radio Rx Timeout event
- */
-static void OnRadioRxTimeout( void );
-
-/*!
- * \brief Function executed on Resend Frame timer event.
- */
-static void OnMacStateCheckTimerEvent( void );
-
-/*!
- * \brief Function executed on duty cycle delayed Tx  timer event
- */
-static void OnTxDelayedTimerEvent( void );
-
-/*!
- * \brief Function executed on first Rx window timer event
- */
-static void OnRxWindow1TimerEvent( void );
-
-/*!
- * \brief Function executed on second Rx window timer event
- */
-static void OnRxWindow2TimerEvent( void );
-
-/*!
- * \brief Function executed on AckTimeout timer event
- */
-static void OnAckTimeoutTimerEvent( void );
-
-/*!
- * \brief Searches and set the next random available channel
- *
- * \param [OUT] Time to wait for the next transmission according to the duty
- *              cycle.
- *
- * \retval status  Function status [1: OK, 0: Unable to find a channel on the
- *                                  current datarate]
- */
-static bool SetNextChannel( TimerTime_t* time );
-
-/*!
- * \brief Sets the network to public or private. Updates the sync byte.
- *
- * \param [IN] enable if true, it enables a public network
- */
-static void SetPublicNetwork( bool enable );
-
-/*!
- * \brief Initializes and opens the reception window
- *
- * \param [IN] freq window channel frequency
- * \param [IN] datarate window channel datarate
- * \param [IN] bandwidth window channel bandwidth
- * \param [IN] timeout window channel timeout
- */
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous );
-
-/*!
- * \brief Verifies if the RX window 2 frequency is in range
- *
- * \param [IN] freq window channel frequency
- *
- * \retval status  Function status [1: OK, 0: Frequency not applicable]
- */
-static bool Rx2FreqInRange( uint32_t freq );
-
-
-/*!
- * \brief Adds a new MAC command to be sent.
- *
- * \Remark MAC layer internal function
- *
- * \param [in] cmd MAC command to be added
- *                 [MOTE_MAC_LINK_CHECK_REQ,
- *                  MOTE_MAC_LINK_ADR_ANS,
- *                  MOTE_MAC_DUTY_CYCLE_ANS,
- *                  MOTE_MAC_RX2_PARAM_SET_ANS,
- *                  MOTE_MAC_DEV_STATUS_ANS
- *                  MOTE_MAC_NEW_CHANNEL_ANS]
- * \param [in] p1  1st parameter ( optional depends on the command )
- * \param [in] p2  2nd parameter ( optional depends on the command )
- *
- * \retval status  Function status [0: OK, 1: Unknown command, 2: Buffer full]
- */
-static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );
-
-/*!
- * \brief Parses the MAC commands which must be repeated.
- *
- * \Remark MAC layer internal function
- *
- * \param [IN] cmdBufIn  Buffer which stores the MAC commands to send
- * \param [IN] length  Length of the input buffer to parse
- * \param [OUT] cmdBufOut  Buffer which stores the MAC commands which must be
- *                         repeated.
- *
- * \retval Size of the MAC commands to repeat.
- */
-static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut );
-
-/*!
- * \brief Validates if the payload fits into the frame, taking the datarate
- *        into account.
- *
- * \details Refer to chapter 4.3.2 of the LoRaWAN specification, v1.0
- *
- * \param lenN Length of the application payload. The length depends on the
- *             datarate and is region specific
- *
- * \param datarate Current datarate
- *
- * \param fOptsLen Length of the fOpts field
- *
- * \retval [false: payload does not fit into the frame, true: payload fits into
- *          the frame]
- */
-static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen );
-
-/*!
- * \brief Counts the number of bits in a mask.
- *
- * \param [IN] mask A mask from which the function counts the active bits.
- * \param [IN] nbBits The number of bits to check.
- *
- * \retval Number of enabled bits in the mask.
- */
-static uint8_t CountBits( uint16_t mask, uint8_t nbBits );
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-/*!
- * \brief Counts the number of enabled 125 kHz channels in the channel mask.
- *        This function can only be applied to US915 band.
- *
- * \param [IN] channelsMask Pointer to the first element of the channel mask
- *
- * \retval Number of enabled channels in the channel mask
- */
-static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask );
-
-#if defined( USE_BAND_915_HYBRID )
-/*!
- * \brief Validates the correctness of the channel mask for US915, hybrid mode.
- *
- * \param [IN] mask Block definition to set.
- * \param [OUT] channelsMask Pointer to the first element of the channel mask
- */
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask );
-
-/*!
- * \brief Validates the correctness of the channel mask for US915, hybrid mode.
- *
- * \param [IN] channelsMask Pointer to the first element of the channel mask
- *
- * \retval [true: channel mask correct, false: channel mask not correct]
- */
-static bool ValidateChannelMask( uint16_t* channelMask );
-#endif
-
-#endif
-
-/*!
- * \brief Limits the Tx power according to the number of enabled channels
- *
- * \retval Returns the maximum valid tx power
- */
-static int8_t LimitTxPower( int8_t txPower );
-
-/*!
- * \brief Verifies, if a value is in a given range.
- *
- * \param value Value to verify, if it is in range
- *
- * \param min Minimum possible value
- *
- * \param max Maximum possible value
- *
- * \retval Returns the maximum valid tx power
- */
-static bool ValueInRange( int8_t value, int8_t min, int8_t max );
-
-/*!
- * \brief Calculates the next datarate to set, when ADR is on or off
- *
- * \param [IN] adrEnabled Specify whether ADR is on or off
- *
- * \param [IN] isTx Set to true if called by transmit, set to false if a dry run
- *
- * \param [OUT] datarateOut Reports the datarate which will be used next
- *
- * \param [OUT] txpowerOut Reports the tx power which will be used next
- *
- * \retval Returns the state of ADR ack request
- */
-static bool AdrNextDr( bool adrEnabled, bool isTx, int8_t* datarateOut, int8_t* txpowerOut );
-
-/*!
- * \brief Disables channel in a specified channel mask
- *
- * \param [IN] id - Id of the channel
- *
- * \param [IN] mask - Pointer to the channel mask to edit
- *
- * \retval [true, if disable was successful, false if not]
- */
-static bool DisableChannelInMask( uint8_t id, uint16_t* mask );
-
-/*!
- * \brief Decodes MAC commands in the fOpts field and in the payload
- */
-static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr );
-
-/*!
- * \brief LoRaMAC layer generic send frame
- *
- * \param [IN] macHdr      MAC header field
- * \param [IN] fPort       MAC payload port
- * \param [IN] fBuffer     MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status          Status of the operation.
- */
-LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*!
- * \brief LoRaMAC layer frame buffer initialization
- *
- * \param [IN] macHdr      MAC header field
- * \param [IN] fCtrl       MAC frame control field
- * \param [IN] fOpts       MAC commands buffer
- * \param [IN] fPort       MAC payload port
- * \param [IN] fBuffer     MAC data buffer to be sent
- * \param [IN] fBufferSize MAC data buffer size
- * \retval status          Status of the operation.
- */
-LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize );
-
-/*
- * \brief Schedules the frame according to the duty cycle
- *
- * \retval Status of the operation
- */
-static LoRaMacStatus_t ScheduleTx( void );
-
-/*
- * \brief Calculates the back-off time for the band of a channel.
- *
- * \param [IN] channel     The last Tx channel index
- */
-static void CalculateBackOff( uint8_t channel );
-
-/*!
- * \brief LoRaMAC layer prepared frame buffer transmission with channel specification
- *
- * \remark PrepareFrame must be called at least once before calling this
- *         function.
- *
- * \param [IN] channel     Channel parameters
- * \retval status          Status of the operation.
- */
-LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel );
-
-
-
-static void OnRadioTxDone( void )
-{
-    TimerTime_t curTime = TimerGetCurrentTime( );
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
-    }
-    else
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    // Store last Tx channel
-    LastTxChannel = Channel;
-    // Update last tx done time for the current channel
-    Bands[Channels[LastTxChannel].Band].LastTxDoneTime = curTime;
-    // Update Aggregated last tx done time
-    AggregatedLastTxDoneTime = curTime;
-
-    // Update join tx done and time on air 
-    if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) && ( MlmeConfirm.MlmeRequest == MLME_JOIN ) )
-    {
-        JoinAggTimeOnAir += TxTimeOnAir;
-        LastJoinTxTime    = curTime;
-    }
-
-    if( IsRxWindowsEnabled == true )
-    {
-        TimerSetValue( &RxWindowTimer1, RxWindow1Delay );
-        TimerStart( &RxWindowTimer1 );
-        if( LoRaMacDeviceClass != CLASS_C )
-        {
-            TimerSetValue( &RxWindowTimer2, RxWindow2Delay );
-            TimerStart( &RxWindowTimer2 );
-        }
-        if( ( LoRaMacDeviceClass == CLASS_C ) || ( NodeAckRequested == true ) )
-        {
-            TimerSetValue( &AckTimeoutTimer, RxWindow2Delay + ACK_TIMEOUT +
-                                             randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) );
-            TimerStart( &AckTimeoutTimer );
-        }
-    }
-    else
-    {
-        McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
-
-        if( LoRaMacFlags.Value == 0 )
-        {
-            LoRaMacFlags.Bits.McpsReq = 1;
-        }
-        LoRaMacFlags.Bits.MacDone = 1;
-    }
-
-    if( NodeAckRequested == false )
-    {
-        McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-        ChannelsNbRepCounter++;
-    }
-}
-
-static void PrepareRxDoneAbort( void )
-{
-    LoRaMacState |= MAC_RX_ABORT;
-
-    if( NodeAckRequested )
-    {
-        OnAckTimeoutTimerEvent( );
-    }
-
-    if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    LoRaMacFlags.Bits.McpsInd = 1;
-    LoRaMacFlags.Bits.MacDone = 1;
-
-    // Trig OnMacCheckTimerEvent call as soon as possible
-    TimerSetValue( &MacStateCheckTimer, 1000 );
-    TimerStart( &MacStateCheckTimer );
-}
-
-static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr )
-{
-    LoRaMacHeader_t macHdr;
-    LoRaMacFrameCtrl_t fCtrl;
-    bool skipIndication = false;
-
-    uint8_t pktHeaderLen = 0;
-    uint32_t address = 0;
-    uint8_t appPayloadStartIndex = 0;
-    uint8_t port = 0xFF;
-    uint8_t frameLen = 0;
-    uint32_t mic = 0;
-    uint32_t micRx = 0;
-
-    uint16_t sequenceCounter = 0;
-    uint16_t sequenceCounterPrev = 0;
-    uint16_t sequenceCounterDiff = 0;
-    uint32_t downLinkCounter = 0;
-
-    MulticastParams_t *curMulticastParams = NULL;
-    uint8_t *nwkSKey = LoRaMacNwkSKey;
-    uint8_t *appSKey = LoRaMacAppSKey;
-
-    uint8_t multicast = 0;
-
-    bool isMicOk = false;
-
-    McpsConfirm.AckReceived = false;
-    McpsIndication.Rssi = rssi;
-    McpsIndication.Snr = snr;
-    McpsIndication.RxSlot = RxSlot;
-    McpsIndication.Port = 0;
-    McpsIndication.Multicast = 0;
-    McpsIndication.FramePending = 0;
-    McpsIndication.Buffer = NULL;
-    McpsIndication.BufferSize = 0;
-    McpsIndication.RxData = false;
-    McpsIndication.AckReceived = false;
-    McpsIndication.DownLinkCounter = 0;
-    McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
-
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
-    }
-    TimerStop( &RxWindowTimer2 );
-
-    macHdr.Value = payload[pktHeaderLen++];
-
-    switch( macHdr.Bits.MType )
-    {
-        case FRAME_TYPE_JOIN_ACCEPT:
-            if( IsLoRaMacNetworkJoined == true )
-            {
-                break;
-            }
-            LoRaMacJoinDecrypt( payload + 1, size - 1, LoRaMacAppKey, LoRaMacRxPayload + 1 );
-
-            LoRaMacRxPayload[0] = macHdr.Value;
-
-            LoRaMacJoinComputeMic( LoRaMacRxPayload, size - LORAMAC_MFR_LEN, LoRaMacAppKey, &mic );
-
-            micRx |= ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN];
-            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 1] << 8 );
-            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 2] << 16 );
-            micRx |= ( ( uint32_t )LoRaMacRxPayload[size - LORAMAC_MFR_LEN + 3] << 24 );
-
-            if( micRx == mic )
-            {
-                LoRaMacJoinComputeSKeys( LoRaMacAppKey, LoRaMacRxPayload + 1, LoRaMacDevNonce, LoRaMacNwkSKey, LoRaMacAppSKey );
-
-                LoRaMacNetID = ( uint32_t )LoRaMacRxPayload[4];
-                LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[5] << 8 );
-                LoRaMacNetID |= ( ( uint32_t )LoRaMacRxPayload[6] << 16 );
-
-                LoRaMacDevAddr = ( uint32_t )LoRaMacRxPayload[7];
-                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[8] << 8 );
-                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[9] << 16 );
-                LoRaMacDevAddr |= ( ( uint32_t )LoRaMacRxPayload[10] << 24 );
-
-                // DLSettings
-                Rx1DrOffset = ( LoRaMacRxPayload[11] >> 4 ) & 0x07;
-                Rx2Channel.Datarate = LoRaMacRxPayload[11] & 0x0F;
-                // RxDelay
-                ReceiveDelay1 = ( LoRaMacRxPayload[12] & 0x0F );
-                if( ReceiveDelay1 == 0 )
-                {
-                    ReceiveDelay1 = 1;
-                }
-                ReceiveDelay1 *= 1e6;
-                ReceiveDelay2 = ReceiveDelay1 + 1e6;
-
-#if !( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-                //CFList
-                if( ( size - 1 ) > 16 )
-                {
-                    ChannelParams_t param;
-                    param.DrRange.Value = ( DR_5 << 4 ) | DR_0;
-
-                    LoRaMacState |= MAC_TX_CONFIG;
-                    for( uint8_t i = 3, j = 0; i < ( 5 + 3 ); i++, j += 3 )
-                    {
-                        param.Frequency = ( ( uint32_t )LoRaMacRxPayload[13 + j] | ( ( uint32_t )LoRaMacRxPayload[14 + j] << 8 ) | ( ( uint32_t )LoRaMacRxPayload[15 + j] << 16 ) ) * 100;
-                        LoRaMacChannelAdd( i, param );
-                    }
-                    LoRaMacState &= ~MAC_TX_CONFIG;
-                }
-#endif
-                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                IsLoRaMacNetworkJoined = true;
-               
-                // Do not change the datarate
-                // ChannelsDatarate = ChannelsDefaultDatarate;
-            }
-            else
-            {
-                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL;
-            }
-            break;
-        case FRAME_TYPE_DATA_CONFIRMED_DOWN:
-        case FRAME_TYPE_DATA_UNCONFIRMED_DOWN:
-            {
-                address = payload[pktHeaderLen++];
-                address |= ( (uint32_t)payload[pktHeaderLen++] << 8 );
-                address |= ( (uint32_t)payload[pktHeaderLen++] << 16 );
-                address |= ( (uint32_t)payload[pktHeaderLen++] << 24 );
-
-                if( address != LoRaMacDevAddr )
-                {
-                    curMulticastParams = MulticastChannels;
-                    while( curMulticastParams != NULL )
-                    {
-                        if( address == curMulticastParams->Address )
-                        {
-                            multicast = 1;
-                            nwkSKey = curMulticastParams->NwkSKey;
-                            appSKey = curMulticastParams->AppSKey;
-                            downLinkCounter = curMulticastParams->DownLinkCounter;
-                            break;
-                        }
-                        curMulticastParams = curMulticastParams->Next;
-                    }
-                    if( multicast == 0 )
-                    {
-                        // We are not the destination of this frame.
-                        McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL;
-                        PrepareRxDoneAbort( );
-                        return;
-                    }
-                }
-                else
-                {
-                    multicast = 0;
-                    nwkSKey = LoRaMacNwkSKey;
-                    appSKey = LoRaMacAppSKey;
-                    downLinkCounter = DownLinkCounter;
-                }
-
-                fCtrl.Value = payload[pktHeaderLen++];
-
-                sequenceCounter = ( uint16_t )payload[pktHeaderLen++];
-                sequenceCounter |= ( uint16_t )payload[pktHeaderLen++] << 8;
-
-                appPayloadStartIndex = 8 + fCtrl.Bits.FOptsLen;
-
-                micRx |= ( uint32_t )payload[size - LORAMAC_MFR_LEN];
-                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 1] << 8 );
-                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 2] << 16 );
-                micRx |= ( ( uint32_t )payload[size - LORAMAC_MFR_LEN + 3] << 24 );
-
-                sequenceCounterPrev = ( uint16_t )downLinkCounter;
-                sequenceCounterDiff = ( sequenceCounter - sequenceCounterPrev );
-
-                if( sequenceCounterDiff < ( 1 << 15 ) )
-                {
-                    downLinkCounter += sequenceCounterDiff;
-                    LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounter, &mic );
-                    if( micRx == mic )
-                    {
-                        isMicOk = true;
-                    }
-                }
-                else
-                {
-                    // check for sequence roll-over
-                    uint32_t  downLinkCounterTmp = downLinkCounter + 0x10000 + ( int16_t )sequenceCounterDiff;
-                    LoRaMacComputeMic( payload, size - LORAMAC_MFR_LEN, nwkSKey, address, DOWN_LINK, downLinkCounterTmp, &mic );
-                    if( micRx == mic )
-                    {
-                        isMicOk = true;
-                        downLinkCounter = downLinkCounterTmp;
-                    }
-                }
-
-                // Check for a the maximum allowed counter difference
-                if( sequenceCounterDiff >= MAX_FCNT_GAP )
-                {
-                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS;
-                    McpsIndication.DownLinkCounter = downLinkCounter;
-                    PrepareRxDoneAbort( );
-                    return;
-                }
-
-                if( isMicOk == true )
-                {
-                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                    McpsIndication.Multicast = multicast;
-                    McpsIndication.FramePending = fCtrl.Bits.FPending;
-                    McpsIndication.Buffer = NULL;
-                    McpsIndication.BufferSize = 0;
-                    McpsIndication.DownLinkCounter = downLinkCounter;
-
-                    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-
-                    AdrAckCounter = 0;
-                    MacCommandsBufferToRepeatIndex = 0;
-
-                    // Update 32 bits downlink counter
-                    if( multicast == 1 )
-                    {
-                        McpsIndication.McpsIndication = MCPS_MULTICAST;
-
-                        if( ( curMulticastParams->DownLinkCounter == downLinkCounter ) &&
-                            ( curMulticastParams->DownLinkCounter != 0 ) )
-                        {
-                            McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
-                            McpsIndication.DownLinkCounter = downLinkCounter;
-                            PrepareRxDoneAbort( );
-                            return;
-                        }
-                        curMulticastParams->DownLinkCounter = downLinkCounter;
-                    }
-                    else
-                    {
-                        if( macHdr.Bits.MType == FRAME_TYPE_DATA_CONFIRMED_DOWN )
-                        {
-                            SrvAckRequested = true;
-                            McpsIndication.McpsIndication = MCPS_CONFIRMED;
-
-                            if( ( DownLinkCounter == downLinkCounter ) &&
-                                ( DownLinkCounter != 0 ) )
-                            {
-                                // Duplicated confirmed downlink. Skip indication.
-                                skipIndication = true;
-                            }
-                        }
-                        else
-                        {
-                            SrvAckRequested = false;
-                            McpsIndication.McpsIndication = MCPS_UNCONFIRMED;
-
-                            if( ( DownLinkCounter == downLinkCounter ) &&
-                                ( DownLinkCounter != 0 ) )
-                            {
-                                McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED;
-                                McpsIndication.DownLinkCounter = downLinkCounter;
-                                PrepareRxDoneAbort( );
-                                return;
-                            }
-                        }
-                        DownLinkCounter = downLinkCounter;
-                    }
-
-
-                    if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
-                    {
-                        port = payload[appPayloadStartIndex++];
-                        frameLen = ( size - 4 ) - appPayloadStartIndex;
-
-                        McpsIndication.Port = port;
-
-                        if( port == 0 )
-                        {
-                            if( fCtrl.Bits.FOptsLen == 0 )
-                            {
-                                LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
-                                                       frameLen,
-                                                       nwkSKey,
-                                                       address,
-                                                       DOWN_LINK,
-                                                       downLinkCounter,
-                                                       LoRaMacRxPayload );
-
-                                // Decode frame payload MAC commands
-                                ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
-                            }
-                            else
-                            {
-                                skipIndication = true;
-                            }
-                        }
-                        else
-                        {
-                            if( fCtrl.Bits.FOptsLen > 0 )
-                            {
-                                // Decode Options field MAC commands. Omit the fPort.
-                                ProcessMacCommands( payload, 8, appPayloadStartIndex - 1, snr );
-                            }
-
-                            LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
-                                                   frameLen,
-                                                   appSKey,
-                                                   address,
-                                                   DOWN_LINK,
-                                                   downLinkCounter,
-                                                   LoRaMacRxPayload );
-
-                            if( skipIndication == false )
-                            {
-                                McpsIndication.Buffer = LoRaMacRxPayload;
-                                McpsIndication.BufferSize = frameLen;
-                                McpsIndication.RxData = true;
-                            }
-                        }
-                    }
-                    else
-                    {
-                        if( fCtrl.Bits.FOptsLen > 0 )
-                        {
-                            // Decode Options field MAC commands
-                            ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
-                        }
-                    }
-
-                    if( skipIndication == false )
-                    {
-                         // Check if the frame is an acknowledgement
-                         if( fCtrl.Bits.Ack == 1 )
-                         {
-                         	McpsConfirm.AckReceived = true;
-                         	McpsIndication.AckReceived = true;
-                         	
-                         	// Stop the AckTimeout timer as no more retransmissions
-                         	// are needed.
-                         	TimerStop( &AckTimeoutTimer );
-                         }
-                         else
-                         {
-                         	McpsConfirm.AckReceived = false;
-                         	
-                         	if( AckTimeoutRetriesCounter > AckTimeoutRetries )
-                         	{
-                         		// Stop the AckTimeout timer as no more retransmissions
-                         		// are needed.
-                         		TimerStop( &AckTimeoutTimer );
-                         	}
-                        }
-                        LoRaMacFlags.Bits.McpsInd = 1;
-                    }
-                }
-                else
-                {
-                    McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_MIC_FAIL;
-
-                    PrepareRxDoneAbort( );
-                    return;
-                }
-            }
-            break;
-        case FRAME_TYPE_PROPRIETARY:
-            {
-                memcpy1( LoRaMacRxPayload, &payload[pktHeaderLen], size );
-
-                McpsIndication.McpsIndication = MCPS_PROPRIETARY;
-                McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                McpsIndication.Buffer = LoRaMacRxPayload;
-                McpsIndication.BufferSize = size - pktHeaderLen;
-
-                LoRaMacFlags.Bits.McpsInd = 1;
-                break;
-            }
-        default:
-            McpsIndication.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-            PrepareRxDoneAbort( );
-            break;
-    }
-
-    if( ( RxSlot == 0 ) && ( LoRaMacDeviceClass == CLASS_C ) )
-    {
-        OnRxWindow2TimerEvent( );
-    }
-    LoRaMacFlags.Bits.MacDone = 1;
-
-    // Trig OnMacCheckTimerEvent call as soon as possible
-    TimerSetValue( &MacStateCheckTimer, 1000 );
-    TimerStart( &MacStateCheckTimer );
-}
-
-static void OnRadioTxTimeout( void )
-{
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
-    }
-    else
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
-    MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT;
-    LoRaMacFlags.Bits.MacDone = 1;
-}
-
-static void OnRadioRxError( void )
-{
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
-    }
-    else
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    if( RxSlot == 1 )
-    {
-        if( NodeAckRequested == true )
-        {
-            McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
-        }
-        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_ERROR;
-        LoRaMacFlags.Bits.MacDone = 1;
-    }
-}
-
-static void OnRadioRxTimeout( void )
-{
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        Radio.Sleep( );
-    }
-    else
-    {
-        OnRxWindow2TimerEvent( );
-    }
-
-    if( RxSlot == 1 )
-    {
-        if( NodeAckRequested == true )
-        {
-            McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
-        }
-        MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT;
-        LoRaMacFlags.Bits.MacDone = 1;
-    }
-}
-
-static void OnMacStateCheckTimerEvent( void )
-{
-    TimerStop( &MacStateCheckTimer );
-    bool txTimeout = false;
-
-    if( LoRaMacFlags.Bits.MacDone == 1 )
-    {
-        if( ( LoRaMacState & MAC_RX_ABORT ) == MAC_RX_ABORT )
-        {
-            LoRaMacState &= ~MAC_RX_ABORT;
-            LoRaMacState &= ~MAC_TX_RUNNING;
-        }
-
-        if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
-        {
-            if( ( McpsConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) ||
-                ( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT ) )
-            {
-                // Stop transmit cycle due to tx timeout.
-                LoRaMacState &= ~MAC_TX_RUNNING;
-                McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
-                McpsConfirm.AckReceived = false;
-                McpsConfirm.TxTimeOnAir = 0;
-                txTimeout = true;
-            }
-        }
-
-        if( ( NodeAckRequested == false ) && ( txTimeout == false ) )
-        {
-            if( LoRaMacFlags.Bits.MlmeReq == 1 )
-            {
-                if( MlmeConfirm.MlmeRequest == MLME_JOIN )
-                {
-                    if( MlmeConfirm.Status == LORAMAC_EVENT_INFO_STATUS_OK )
-                    {
-                        UpLinkCounter = 0;
-                    }
-                    // Join messages aren't repeated automatically
-                    ChannelsNbRepCounter = ChannelsNbRep;
-                }
-            }
-            if( ( LoRaMacFlags.Bits.MlmeReq == 1 ) || ( ( LoRaMacFlags.Bits.McpsReq == 1 ) ) )
-            {
-                if( ( ChannelsNbRepCounter >= ChannelsNbRep ) || ( LoRaMacFlags.Bits.McpsInd == 1 ) )
-                {
-                    ChannelsNbRepCounter = 0;
-
-                    AdrAckCounter++;
-                    if( IsUpLinkCounterFixed == false )
-                    {
-                        UpLinkCounter++;
-                    }
-
-                    LoRaMacState &= ~MAC_TX_RUNNING;
-                }
-                else
-                {
-                    LoRaMacFlags.Bits.MacDone = 0;
-                    // Sends the same frame again
-                    ScheduleTx( );
-                }
-            }
-        }
-
-        if( LoRaMacFlags.Bits.McpsInd == 1 )
-        {
-            if( ( McpsConfirm.AckReceived == true ) || ( AckTimeoutRetriesCounter > AckTimeoutRetries ) )
-            {
-                AckTimeoutRetry = false;
-                NodeAckRequested = false;
-                if( IsUpLinkCounterFixed == false )
-                {
-                    UpLinkCounter++;
-                }
-                McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
-
-                LoRaMacState &= ~MAC_TX_RUNNING;
-            }
-        }
-
-        if( ( AckTimeoutRetry == true ) && ( ( LoRaMacState & MAC_TX_DELAYED ) == 0 ) )
-        {
-            AckTimeoutRetry = false;
-            if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) )
-            {
-                AckTimeoutRetriesCounter++;
-
-                if( ( AckTimeoutRetriesCounter % 2 ) == 1 )
-                {
-                    ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_TX_MIN_DATARATE );
-                    // Check if new datarate is valid for the Payload length
-					if( ValidatePayloadLength( LoRaMacBufferPktLen - 13, ChannelsDatarate, 0 ) == false )
-					{							
-						// If invalid payload length, then revert to previous datarate
-						ChannelsDatarate++;
-					}
-                }
-                LoRaMacFlags.Bits.MacDone = 0;
-                // Sends the same frame again
-                ScheduleTx( );
-            }
-            else
-            {
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-                // Re-enable default channels LC1, LC2, LC3
-                ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
-#elif !defined( USE_BAND_915 ) && !defined( USE_BAND_915_HYBRID )
-    #error "Please define a frequency band in the compiler options."
-#endif
-                LoRaMacState &= ~MAC_TX_RUNNING;
-
-                NodeAckRequested = false;
-                McpsConfirm.AckReceived = false;
-                McpsConfirm.NbRetries = AckTimeoutRetriesCounter;
-                if( IsUpLinkCounterFixed == false )
-                {
-                    UpLinkCounter++;
-                }
-            }
-        }
-    }
-    // Handle reception for Class B and Class C
-    if( ( LoRaMacState & MAC_RX ) == MAC_RX )
-    {
-        LoRaMacState &= ~MAC_RX;
-    }
-    if( LoRaMacState == MAC_IDLE )
-    {
-        if( LoRaMacFlags.Bits.McpsReq == 1 )
-        {
-            LoRaMacPrimitives->MacMcpsConfirm( &McpsConfirm );
-            LoRaMacFlags.Bits.McpsReq = 0;
-        }
-
-        if( LoRaMacFlags.Bits.MlmeReq == 1 )
-        {
-            LoRaMacPrimitives->MacMlmeConfirm( &MlmeConfirm );
-            LoRaMacFlags.Bits.MlmeReq = 0;
-        }
-
-        LoRaMacFlags.Bits.MacDone = 0;
-    }
-    else
-    {
-        // Operation not finished restart timer
-        TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
-        TimerStart( &MacStateCheckTimer );
-    }
-
-    if( LoRaMacFlags.Bits.McpsInd == 1 )
-    {
-        LoRaMacPrimitives->MacMcpsIndication( &McpsIndication );
-        LoRaMacFlags.Bits.McpsInd = 0;
-    }
-}
-
-static void OnTxDelayedTimerEvent( void )
-{
-    TimerStop( &TxDelayedTimer );
-    LoRaMacState &= ~MAC_TX_DELAYED;
-
-    ScheduleTx( );
-}
-
-static void OnRxWindow1TimerEvent( void )
-{
-    uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
-    int8_t datarate = 0;
-    uint32_t bandwidth = 0; // LoRa 125 kHz
-
-    TimerStop( &RxWindowTimer1 );
-    RxSlot = 0;
-
-    if( LoRaMacDeviceClass == CLASS_C )
-    {
-        Radio.Standby( );
-    }
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    datarate = ChannelsDatarate - Rx1DrOffset;
-    if( datarate < 0 )
-    {
-        datarate = DR_0;
-    }
-
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    if( ( datarate == DR_3 ) || ( datarate == DR_4 ) )
-    { // DR_4, DR_3
-        symbTimeout = 8;
-    }
-    else if( datarate == DR_5 )
-    {
-        symbTimeout = 10;
-    }
-    else if( datarate == DR_6 )
-    {// LoRa 250 kHz
-        bandwidth  = 1;
-        symbTimeout = 14;
-    }
-    RxWindowSetup( Channels[Channel].Frequency, datarate, bandwidth, symbTimeout, false );
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    datarate = datarateOffsets[ChannelsDatarate][Rx1DrOffset];
-    if( datarate < 0 )
-    {
-        datarate = DR_0;
-    }
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    switch( datarate )
-    {
-        case DR_0:       // SF10 - BW125
-            symbTimeout = 5;
-            break;
-
-        case DR_1:       // SF9  - BW125
-        case DR_2:       // SF8  - BW125
-        case DR_8:       // SF12 - BW500
-        case DR_9:       // SF11 - BW500
-        case DR_10:      // SF10 - BW500
-            symbTimeout = 8;
-            break;
-
-        case DR_3:       // SF7  - BW125
-        case DR_11:      // SF9  - BW500
-            symbTimeout = 10;
-            break;
-
-        case DR_4:       // SF8  - BW500
-        case DR_12:      // SF8  - BW500
-            symbTimeout = 14;
-            break;
-
-        case DR_13:      // SF7  - BW500
-            symbTimeout = 16;
-            break;
-        default:
-            break;
-    }
-    if( datarate >= DR_4 )
-    {// LoRa 500 kHz
-        bandwidth  = 2;
-    }
-    RxWindowSetup( 923.3e6 + ( Channel % 8 ) * 600e3, datarate, bandwidth, symbTimeout, false );
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-}
-
-static void OnRxWindow2TimerEvent( void )
-{
-    uint16_t symbTimeout = 5; // DR_2, DR_1, DR_0
-    uint32_t bandwidth = 0; // LoRa 125 kHz
-
-    TimerStop( &RxWindowTimer2 );
-    RxSlot = 1;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    if( ( Rx2Channel.Datarate == DR_3 ) || ( Rx2Channel.Datarate == DR_4 ) )
-    { // DR_4, DR_3
-        symbTimeout = 8;
-    }
-    else if( Rx2Channel.Datarate == DR_5 )
-    {
-        symbTimeout = 10;
-    }
-    else if( Rx2Channel.Datarate == DR_6 )
-    {// LoRa 250 kHz
-        bandwidth  = 1;
-        symbTimeout = 14;
-    }
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    // For higher datarates, we increase the number of symbols generating a Rx Timeout
-    switch( Rx2Channel.Datarate )
-    {
-        case DR_0:       // SF10 - BW125
-            symbTimeout = 5;
-            break;
-
-        case DR_1:       // SF9  - BW125
-        case DR_2:       // SF8  - BW125
-        case DR_8:       // SF12 - BW500
-        case DR_9:       // SF11 - BW500
-        case DR_10:      // SF10 - BW500
-            symbTimeout = 8;
-            break;
-
-        case DR_3:       // SF7  - BW125
-        case DR_11:      // SF9  - BW500
-            symbTimeout = 10;
-            break;
-
-        case DR_4:       // SF8  - BW500
-        case DR_12:      // SF8  - BW500
-            symbTimeout = 14;
-            break;
-
-        case DR_13:      // SF7  - BW500
-            symbTimeout = 16;
-            break;
-        default:
-            break;
-    }
-    if( Rx2Channel.Datarate >= DR_4 )
-    {// LoRa 500 kHz
-        bandwidth  = 2;
-    }
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-    if( LoRaMacDeviceClass != CLASS_C )
-    {
-        RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, false );
-    }
-    else
-    {
-        RxWindowSetup( Rx2Channel.Frequency, Rx2Channel.Datarate, bandwidth, symbTimeout, true );
-    }
-}
-
-static void OnAckTimeoutTimerEvent( void )
-{
-    TimerStop( &AckTimeoutTimer );
-
-    if( NodeAckRequested == true )
-    {
-        AckTimeoutRetry = true;
-        LoRaMacState &= ~MAC_ACK_REQ;
-    }
-    if( LoRaMacDeviceClass == CLASS_C )
-    {
-        LoRaMacFlags.Bits.MacDone = 1;
-    }
-}
-
-#if defined( USE_BAND_915 ) 
-uint8_t GetNextJoinChannel( uint8_t* enabledChannels, uint8_t nbEnabledChannels )
-{ 
-    int8_t   channel = -1;
-    uint8_t  block;
-    uint8_t  i;
-
-    // Use 125KHz channel
-    if( ChannelsDatarate < DR_4 )
-    {
-        block = JoinBlock[NextJoinBlock]; 
-        NextJoinBlock = (NextJoinBlock + 1) % 8;
-
-        // If next block is greater than max block then randomly select the next block   
-        if( block >= 8 )
-            block = randr(0, 7);
-
-        // Start search for next join channel at the selected block
-        for(i = 0; ( i < 8 ) && ( channel == -1 ); i++)
-        {
-            uint8_t curBlock = (block + i) % 8;
-            uint8_t chMask;
-
-            // Cycle through all blocks before using a previously used block             
-            if( ( ( JoinBlocksRemaining & ( 1 <<  curBlock ) ) != 0) ) 
-            {
-                chMask = ( ChannelsMaskRemaining[curBlock/2] >> ( curBlock & 1 ? 8 : 0 ) ) & 0xff; 
-                if( chMask != 0)
-                { 
-                    channel = randr(0, 7); 
-                    for(uint8_t i = 0; ( i < 8 ); i++)
-                    {                       
-                        if( ( chMask & ( 1 << channel ) ) != 0 )
-                        {
-                            uint16_t chMaskTmp = ( 1 << channel );
-                            chMaskTmp = chMaskTmp << ( curBlock & 1 ? 8 : 0 );
-                            channel = channel + ( curBlock * 8 );
-                            JoinBlocksRemaining &= ~(1 << curBlock);                                                        
-                            ChannelsMaskRemaining[curBlock/2] &= ~chMaskTmp;                            
-                            if( ( JoinBlocksRemaining == 0 ) )
-                            {
-                                JoinBlocksRemaining = 0xFF;
-                            }                           
-                            break;
-                        }
-                        else
-                        {
-                            channel = ( channel + 1 ) % 8;
-                        }
-                    }
-                }
-            }
-        }
-        
-        // No next channel case should never happen since ScheduleTx has already 
-        // checked for at least one enabled channel and if none re-enabled all channels. 
-        // But if we find ourselves without a channel then randomly select one
-        if ( i >= 8 )
-        {
-            channel = randr( 0, 63 );
-        }
-    }
-    // Use 500 KHz channel
-    else 
-    {
-        channel = randr( 0, 7 );
-        for(i = 0; i < 8; i++)
-        {
-            uint8_t curChannel = (channel + i) % 8;
-            
-            if( ( ( Join500KHzRemaining & ( 1 << curChannel ) ) != 0 ) )
-            {
-                Join500KHzRemaining &= ~(1 << curChannel);
-                channel = 64 + curChannel;
-                if( Join500KHzRemaining == 0 )
-                {
-                    Join500KHzRemaining = 0xFF;
-                }
-                break;
-            }
-        }
-    }
-
-    for( i = 0; i < nbEnabledChannels; i++ )
-    {
-        if( enabledChannels[i] == channel )
-            break;
-    }
-
-    if( i == nbEnabledChannels )
-    {
-        channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
-    }
-
-    LastJoinBlock = channel / 8;
-
-    return channel;
-}
-#endif
-
-static bool SetNextChannel( TimerTime_t* time )
-{
-    uint8_t nbEnabledChannels = 0;
-    uint8_t delayTx = 0;
-    uint8_t enabledChannels[LORA_MAX_NB_CHANNELS];
-    TimerTime_t nextTxDelay = ( TimerTime_t )( -1 );
-
-    memset1( enabledChannels, 0, LORA_MAX_NB_CHANNELS );
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    if( CountNbEnabled125kHzChannels( ChannelsMaskRemaining ) == 0 )
-    { // Restore default channels
-        memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 8 );
-    }
-    if( ( ChannelsDatarate >= DR_4 ) && ( ( ChannelsMaskRemaining[4] & 0x00FF ) == 0 ) )
-    { // Make sure, that the channels are activated
-        ChannelsMaskRemaining[4] = ChannelsMask[4];
-    }
-#else
-    if( CountBits( ChannelsMask[0], 16 ) == 0 )
-    {
-        // Re-enable default channels, if no channel is enabled
-        ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
-    }
-#endif
-
-    // Update Aggregated duty cycle
-    if( AggregatedTimeOff <= TimerGetElapsedTime( AggregatedLastTxDoneTime ) )
-    {
-        AggregatedTimeOff = 0;
-
-        // Update bands Time OFF
-        for( uint8_t i = 0; i < LORA_MAX_NB_BANDS; i++ )
-        {
-            if( DutyCycleOn == true )
-            {
-                if( Bands[i].TimeOff <= TimerGetElapsedTime( Bands[i].LastTxDoneTime ) )
-                {
-                    Bands[i].TimeOff = 0;
-                }
-                if( Bands[i].TimeOff != 0 )
-                {
-                    nextTxDelay = MIN( Bands[i].TimeOff -
-                                       TimerGetElapsedTime( Bands[i].LastTxDoneTime ),
-                                       nextTxDelay );
-                }
-            }
-            else
-            {
-                nextTxDelay = 0;
-                Bands[i].TimeOff = 0;
-            }
-        }
-
-        // Search how many channels are enabled
-        for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS; i += 16, k++ )
-        {
-            for( uint8_t j = 0; j < 16; j++ )
-            {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                if( ( ChannelsMaskRemaining[k] & ( 1 << j ) ) != 0 )
-#else
-                if( ( ChannelsMask[k] & ( 1 << j ) ) != 0 )
-#endif
-                {
-                    if( Channels[i + j].Frequency == 0 )
-                    { // Check if the channel is enabled
-                        continue;
-                    }
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
-                    if( IsLoRaMacNetworkJoined == false )
-                    {
-                        if( ( JOIN_CHANNELS & ( 1 << j ) ) == 0 )
-                        {
-                            continue;
-                        }
-                    }
-#endif
-                    if( ( ( Channels[i + j].DrRange.Fields.Min <= ChannelsDatarate ) &&
-                          ( ChannelsDatarate <= Channels[i + j].DrRange.Fields.Max ) ) == false )
-                    { // Check if the current channel selection supports the given datarate
-                        continue;
-                    }
-                    if( Bands[Channels[i + j].Band].TimeOff > 0 )
-                    { // Check if the band is available for transmission
-                        delayTx++;
-                        continue;
-                    }
-                    enabledChannels[nbEnabledChannels++] = i + j;
-                }
-            }
-        }
-    }
-    else
-    {
-        delayTx++;
-        nextTxDelay = AggregatedTimeOff - TimerGetElapsedTime( AggregatedLastTxDoneTime );
-    }
-    
-    if( nbEnabledChannels > 0 )
-    {
-#if defined( USE_BAND_915 ) 
-        if ( IsLoRaMacNetworkJoined == false )
-        {
-            Channel = GetNextJoinChannel(enabledChannels, nbEnabledChannels);
-        }
-        // Send first uplink on channel from same sub-band as the join 
-        else if( ( UpLinkCounter == 1 ) && ( LastJoinBlock != -1 ) )
-        {
-            uint8_t i;
-            uint8_t blockFirstChannel = LastJoinBlock*8;
-
-            Channel = randr( blockFirstChannel, blockFirstChannel + 7 );
-
-            // Check channel is enabled
-            for( i = 0; i < nbEnabledChannels; i++ )
-            {
-                if( Channel == enabledChannels[i] )
-                    break;
-            }
-
-            // If channel is not enabled fallback to selecting from the list of 
-            // enabled  channels
-            if (i == nbEnabledChannels)
-            {
-                Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
-            }
-        }
-        else
-#endif
-        { 
-            Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
-        }
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-        if( Channel < ( LORA_MAX_NB_CHANNELS - 8 ) )
-        {
-            DisableChannelInMask( Channel, ChannelsMaskRemaining );
-        }
-#endif
-        *time = 0;
-        return true;
-    }
-    else
-    {
-        if( delayTx > 0 )
-        {
-            // Delay transmission due to AggregatedTimeOff or to a band time off
-            *time = nextTxDelay;
-            return true;
-        }
-        // Datarate not supported by any channel
-        *time = 0;
-        return false;
-    }
-}
-
-static void SetPublicNetwork( bool enable )
-{
-    PublicNetwork = enable;
-    Radio.SetModem( MODEM_LORA );
-    if( PublicNetwork == true )
-    {
-        // Change LoRa modem SyncWord
-        Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD );
-    }
-    else
-    {
-        // Change LoRa modem SyncWord
-        Radio.Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD );
-    }
-}
-
-static void RxWindowSetup( uint32_t freq, int8_t datarate, uint32_t bandwidth, uint16_t timeout, bool rxContinuous )
-{
-    uint8_t downlinkDatarate = Datarates[datarate];
-    RadioModems_t modem;
-
-    if( Radio.GetStatus( ) == RF_IDLE )
-    {
-        Radio.SetChannel( freq );
-
-        // Store downlink datarate
-        McpsIndication.RxDatarate = ( uint8_t ) datarate;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-        if( datarate == DR_7 )
-        {
-            modem = MODEM_FSK;
-            Radio.SetRxConfig( modem, 50e3, downlinkDatarate * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, rxContinuous );
-        }
-        else
-        {
-            modem = MODEM_LORA;
-            Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
-        }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-        modem = MODEM_LORA;
-        Radio.SetRxConfig( modem, bandwidth, downlinkDatarate, 1, 0, 8, timeout, false, 0, false, 0, 0, true, rxContinuous );
-#endif
-
-        if( RepeaterSupport == true )
-        {
-            Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarateRepeater[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
-        }
-        else
-        {
-            Radio.SetMaxPayloadLength( modem, MaxPayloadOfDatarate[datarate] + LORA_MAC_FRMPAYLOAD_OVERHEAD );
-        }
-
-        if( rxContinuous == false )
-        {
-            Radio.Rx( MaxRxWindow );
-        }
-        else
-        {
-            Radio.Rx( 0 ); // Continuous mode
-        }
-    }
-}
-
-static bool Rx2FreqInRange( uint32_t freq )
-{
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( Radio.CheckRfFrequency( freq ) == true )
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    if( ( Radio.CheckRfFrequency( freq ) == true ) &&
-        ( freq >= LORAMAC_FIRST_RX2_CHANNEL ) &&
-        ( freq <= LORAMAC_LAST_RX2_CHANNEL ) &&
-        ( ( ( freq - ( uint32_t ) LORAMAC_FIRST_RX2_CHANNEL ) % ( uint32_t ) LORAMAC_STEPWIDTH_RX2_CHANNEL ) == 0 ) )
-#endif
-    {
-        return true;
-    }
-    return false;
-}
-
-
-static bool ValidatePayloadLength( uint8_t lenN, int8_t datarate, uint8_t fOptsLen )
-{
-    uint16_t maxN = 0;
-    uint16_t payloadSize = 0;
-
-    // Get the maximum payload length
-    if( RepeaterSupport == true )
-    {
-        maxN = MaxPayloadOfDatarateRepeater[datarate];
-    }
-    else
-    {
-        maxN = MaxPayloadOfDatarate[datarate];
-    }
-
-    // Calculate the resulting payload size
-    payloadSize = ( lenN + fOptsLen );
-
-    // Validation of the application payload size
-    if( ( payloadSize <= maxN ) && ( payloadSize <= LORAMAC_PHY_MAXPAYLOAD ) )
-    {
-        return true;
-    }
-    return false;
-}
-
-static uint8_t CountBits( uint16_t mask, uint8_t nbBits )
-{
-    uint8_t nbActiveBits = 0;
-
-    for( uint8_t j = 0; j < nbBits; j++ )
-    {
-        if( ( mask & ( 1 << j ) ) == ( 1 << j ) )
-        {
-            nbActiveBits++;
-        }
-    }
-    return nbActiveBits;
-}
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-static uint8_t CountNbEnabled125kHzChannels( uint16_t *channelsMask )
-{
-    uint8_t nb125kHzChannels = 0;
-
-    for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
-    {
-        nb125kHzChannels += CountBits( channelsMask[k], 16 );
-    }
-
-    return nb125kHzChannels;
-}
-
-#if defined( USE_BAND_915_HYBRID )
-static void ReenableChannels( uint16_t mask, uint16_t* channelMask )
-{
-    uint16_t blockMask = mask;
-
-    for( uint8_t i = 0, j = 0; i < 4; i++, j += 2 )
-    {
-        channelMask[i] = 0;
-        if( ( blockMask & ( 1 << j ) ) != 0 )
-        {
-            channelMask[i] |= 0x00FF;
-        }
-        if( ( blockMask & ( 1 << ( j + 1 ) ) ) != 0 )
-        {
-            channelMask[i] |= 0xFF00;
-        }
-    }
-    channelMask[4] = blockMask;
-    channelMask[5] = 0x0000;
-}
-
-static bool ValidateChannelMask( uint16_t* channelMask )
-{
-    bool chanMaskState = false;
-    uint16_t block1 = 0;
-    uint16_t block2 = 0;
-    uint8_t index = 0;
-
-    for( uint8_t i = 0; i < 4; i++ )
-    {
-        block1 = channelMask[i] & 0x00FF;
-        block2 = channelMask[i] & 0xFF00;
-
-        if( ( CountBits( block1, 16 ) > 5 ) && ( chanMaskState == false ) )
-        {
-            channelMask[i] &= block1;
-            channelMask[4] = 1 << ( i * 2 );
-            chanMaskState = true;
-            index = i;
-        }
-        else if( ( CountBits( block2, 16 ) > 5 ) && ( chanMaskState == false ) )
-        {
-            channelMask[i] &= block2;
-            channelMask[4] = 1 << ( i * 2 + 1 );
-            chanMaskState = true;
-            index = i;
-        }
-    }
-
-    // Do only change the channel mask, if we have found a valid block.
-    if( chanMaskState == true )
-    {
-        for( uint8_t i = 0; i < 4; i++ )
-        {
-            if( i != index )
-            {
-                channelMask[i] = 0;
-            }
-        }
-    }
-    return chanMaskState;
-}
-#endif
-#endif
-
-static int8_t LimitTxPower( int8_t txPower )
-{
-    int8_t resultTxPower = txPower;
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    if( ( ChannelsDatarate == DR_4 ) ||
-        ( ( ChannelsDatarate >= DR_8 ) && ( ChannelsDatarate <= DR_13 ) ) )
-    {// Limit tx power to max 26dBm
-        resultTxPower =  MAX( txPower, TX_POWER_26_DBM );
-    }
-    else
-    {
-        if( CountNbEnabled125kHzChannels( ChannelsMask ) < FRQ_HOP_CHNLS_MIN )
-        {// Limit tx power to max 21dBm
-            resultTxPower = MAX( txPower, TX_POWER_20_DBM );
-        }
-    }
-#endif
-    return resultTxPower;
-}
-
-static bool ValueInRange( int8_t value, int8_t min, int8_t max )
-{
-    if( ( value >= min ) && ( value <= max ) )
-    {
-        return true;
-    }
-    return false;
-}
-
-static bool DisableChannelInMask( uint8_t id, uint16_t* mask )
-{
-    uint8_t index = 0;
-    index = id / 16;
-
-    if( ( index > 4 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
-    {
-        return false;
-    }
-
-    // Deactivate channel
-    mask[index] &= ~( 1 << ( id % 16 ) );
-
-    return true;
-}
-
-static bool AdrNextDr( bool adrEnabled, bool isTx, int8_t* datarateOut, int8_t* txpowerOut )
-{
-    bool adrAckReq = false;
-    int8_t datarate = ChannelsDatarate;
-    int8_t txpower  = ChannelsTxPower;
-    
-    if( adrEnabled == true )
-    {
-        /* Request ADR Ack Request (including at lowest available datarate) */
-        adrAckReq = AdrAckCounter >= ADR_ACK_LIMIT ? true : false;
-
-        if( AdrAckCounter >= (ADR_ACK_LIMIT + ADR_ACK_DELAY) )
-        {
-            // Step up power
-            txpower = LORAMAC_DEFAULT_TX_POWER;
-
-            if( ( AdrAckCounter % ADR_ACK_DELAY ) == 0 )
-            {
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-                if( datarate > LORAMAC_TX_MIN_DATARATE )
-                {
-                	datarate--;
-                }
-
-                if( datarate == LORAMAC_TX_MIN_DATARATE )
-                {
-                	if( isTx == true )
-                	{
-                		// Re-enable default channels LC1, LC2, LC3
-                		ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
-                	}
-                }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                if( datarate > LORAMAC_TX_MIN_DATARATE )
-                {
-                	if ( datarate == DR_8)
-                		datarate = DR_4;
-                	else
-                		datarate--;
-                }
-                else if( isTx == true )
-                {
-#if defined( USE_BAND_915 )
-                	// Re-enable default channels
-                	ChannelsMask[0] = 0xFFFF;
-                	ChannelsMask[1] = 0xFFFF;
-                	ChannelsMask[2] = 0xFFFF;
-                	ChannelsMask[3] = 0xFFFF;
-                	ChannelsMask[4] = 0x00FF;
-                	ChannelsMask[5] = 0x0000;
-#else // defined( USE_BAND_915_HYBRID )
-                	// Re-enable default channels
-                	ChannelsMask[0] = 0x00FF;
-                	ChannelsMask[1] = 0x0000;
-                	ChannelsMask[2] = 0x0000;
-                	ChannelsMask[3] = 0x0000;
-                	ChannelsMask[4] = 0x0001;
-                	ChannelsMask[5] = 0x0000;
-#endif
-                }
-#else
-#error "Please define a frequency band in the compiler options."
-#endif
-            }
-        }
-    }
-
-    if(datarateOut != NULL)
-        *datarateOut = datarate;
-
-    if(txpowerOut != NULL)
-        *txpowerOut = txpower;
-
-    return adrAckReq;
-    
-}
-
-static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
-    // The maximum buffer length must take MAC commands to re-send into account.
-    uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
-
-    switch( cmd )
-    {
-        case MOTE_MAC_LINK_CHECK_REQ:
-            if( MacCommandsBufferIndex < bufLen )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // No payload for this command
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_LINK_ADR_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 1 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // Margin
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_DUTY_CYCLE_ANS:
-            if( MacCommandsBufferIndex < bufLen )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // No payload for this answer
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_RX_PARAM_SETUP_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 1 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // Status: Datarate ACK, Channel ACK
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_DEV_STATUS_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 2 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // 1st byte Battery
-                // 2nd byte Margin
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p2;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_NEW_CHANNEL_ANS:
-            if( MacCommandsBufferIndex < ( bufLen - 1 ) )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // Status: Datarate range OK, Channel frequency OK
-                MacCommandsBuffer[MacCommandsBufferIndex++] = p1;
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        case MOTE_MAC_RX_TIMING_SETUP_ANS:
-            if( MacCommandsBufferIndex < bufLen )
-            {
-                MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
-                // No payload for this answer
-                status = LORAMAC_STATUS_OK;
-            }
-            break;
-        default:
-            return LORAMAC_STATUS_SERVICE_UNKNOWN;
-    }
-    if( status == LORAMAC_STATUS_OK )
-    {
-        MacCommandsInNextTx = true;
-    }
-    return status;
-}
-
-static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut )
-{
-    uint8_t i = 0;
-    uint8_t cmdCount = 0;
-
-    if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) )
-    {
-        return 0;
-    }
-
-    for( i = 0; i < length; i++ )
-    {
-        switch( cmdBufIn[i] )
-        {
-            case MOTE_MAC_RX_PARAM_SETUP_ANS:
-            {
-                cmdBufOut[cmdCount++] = cmdBufIn[i++];
-                cmdBufOut[cmdCount++] = cmdBufIn[i++];
-                cmdBufOut[cmdCount++] = cmdBufIn[i];
-                break;
-            }
-            case MOTE_MAC_RX_TIMING_SETUP_ANS:
-            {
-                cmdBufOut[cmdCount++] = cmdBufIn[i];
-                break;
-            }
-            default:
-                break;
-        }
-    }
-
-    return cmdCount;
-}
-
-static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
-{
-    uint8_t  validLinkAdrCmds = 0;
-    int8_t   txPower          = 0;
-    int8_t   datarate         = 0;
-    uint8_t  nbRep            = 0;
-    uint16_t channelsMask[6]  = {0,0,0,0,0,0}; 
-    uint8_t  LinkAdrMacCmdBufferIndex = 0;
-
-    while( macIndex < commandsSize )
-    {
-        // Decode Frame MAC commands
-        switch( payload[macIndex++] )
-        {
-            case SRV_MAC_LINK_CHECK_ANS:
-                MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
-                MlmeConfirm.DemodMargin = payload[macIndex++];
-                MlmeConfirm.NbGateways = payload[macIndex++];
-                break;
-            case SRV_MAC_LINK_ADR_REQ:
-                {
-                    uint8_t  chMaskCntl = 0;
-                    uint8_t  status     = 0x07; 
-                    uint16_t chMask;
-
-                    datarate = payload[macIndex++];
-                    txPower  = datarate & 0x0F;
-                    datarate = ( datarate >> 4 ) & 0x0F;
-
-                    if( ( AdrCtrlOn == false ) &&
-                        ( ( ChannelsDatarate != datarate ) || ( ChannelsTxPower != txPower ) ) )
-                    { // ADR disabled don't handle ADR requests if server tries to change datarate or txpower
-                        // Answer the server with fail status
-                        // Power ACK     = 0
-                        // Data rate ACK = 0
-                        // Channel mask  = 0
-                        AddMacCommand( MOTE_MAC_LINK_ADR_ANS, 0, 0 );
-                        macIndex += 3;  // Skip over the remaining bytes of the request
-                        break;
-                    }
-                    else if ( validLinkAdrCmds++ == 0 )
-                    {
-                        // Initialize local copy of the channels mask array
-                        for(uint8_t i = 0; i < 6; i++ )
-                        {
-                            channelsMask[i] = ChannelsMask[i];
-                        }
-                    }
-
-
-                    chMask = ( uint16_t )payload[macIndex++];
-                    chMask |= ( uint16_t )payload[macIndex++] << 8;
-
-                    nbRep = payload[macIndex++];
-                    chMaskCntl = ( nbRep >> 4 ) & 0x07;
-                    nbRep &= 0x0F;
-                    if( nbRep == 0 )
-                    {
-                        nbRep = 1;
-                    }
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-                    if( ( chMaskCntl == 0 ) && ( chMask == 0 ) )
-                    {
-                        status &= 0xFE; // Channel mask KO
-                    }
-                    else if( ( ( chMaskCntl >= 1 ) && ( chMaskCntl <= 5 )) ||
-                             ( chMaskCntl >= 7 ) )
-                    {
-                        // RFU
-                        status &= 0xFE; // Channel mask KO
-                    }
-                    else
-                    {
-                        for( i = 0; i < LORA_MAX_NB_CHANNELS; i++ )
-                        {
-                            if( chMaskCntl == 6 )
-                            {
-                                if( Channels[i].Frequency != 0 )
-                                {
-                                    chMask |= 1 << i;
-                                }
-                            }
-                            else
-                            {
-                                if( ( ( chMask & ( 1 << i ) ) != 0 ) &&
-                                    ( Channels[i].Frequency == 0 ) )
-                                {// Trying to enable an undefined channel
-                                    status &= 0xFE; // Channel mask KO
-                                }
-                            }
-                        }
-                        channelsMask[0] = chMask;
-                    }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                    if( chMaskCntl < 4 )
-                    {
-                        channelsMask[chMaskCntl] = chMask;
-                    }
-                    else if( chMaskCntl == 6 )
-                    {
-                        // Enable all 125 kHz channels
-                        for( uint8_t i = 0, k = 0; i < LORA_MAX_NB_CHANNELS - 8; i += 16, k++ )
-                        {
-                            for( uint8_t j = 0; j < 16; j++ )
-                            {
-                                if( Channels[i + j].Frequency != 0 )
-                                {
-                                    channelsMask[k] |= 1 << j;
-                                }
-                            }
-                        }
-                        // channel mask applied to 500 kHz channels
-                        channelsMask[4] =  chMask; 
-                    }
-                    else if( chMaskCntl == 7 )
-                    {
-                        // Disable all 125 kHz channels
-                        channelsMask[0] = 0x0000;
-                        channelsMask[1] = 0x0000;
-                        channelsMask[2] = 0x0000;
-                        channelsMask[3] = 0x0000;
-
-                        // channel mask applied to 500 kHz channels
-                        channelsMask[4] = chMask;
-                    }
-                    else 
-                    {
-                        // RFU
-                        status &= 0xFE; // Channel mask KO
-                    }
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-                    if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == false )
-                    {
-                        status &= 0xFD; // Datarate KO
-                    }
-
-                    //
-                    // Remark MaxTxPower = 0 and MinTxPower = 5
-                    //
-                    if( ValueInRange( txPower, LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) == false )
-                    {
-                        status &= 0xFB; // TxPower KO
-                    } 
-
-
-                    // Save the mac command status location for possible channel mask KO later
-                    LinkAdrMacCmdBufferIndex = MacCommandsBufferIndex;
-
-                    AddMacCommand( MOTE_MAC_LINK_ADR_ANS, status, 0 );
-                }
-                break;
-            case SRV_MAC_DUTY_CYCLE_REQ:
-                MaxDCycle = payload[macIndex++];
-                AggregatedDCycle = 1 << MaxDCycle;
-                AddMacCommand( MOTE_MAC_DUTY_CYCLE_ANS, 0, 0 );
-                break;
-            case SRV_MAC_RX_PARAM_SETUP_REQ:
-                {
-                    uint8_t status = 0x07;
-                    int8_t datarate = 0;
-                    int8_t drOffset = 0;
-                    uint32_t freq = 0;
-
-                    drOffset = ( payload[macIndex] >> 4 ) & 0x07;
-                    datarate = payload[macIndex] & 0x0F;
-                    macIndex++;
-
-                    freq =  ( uint32_t )payload[macIndex++];
-                    freq |= ( uint32_t )payload[macIndex++] << 8;
-                    freq |= ( uint32_t )payload[macIndex++] << 16;
-                    freq *= 100;
-                    
-                    if( Rx2FreqInRange( freq ) == false )
-                    {
-                        status &= 0xFE; // Channel frequency KO
-                    }
-
-                    if( ValueInRange( datarate, LORAMAC_RX_MIN_DATARATE, LORAMAC_RX_MAX_DATARATE ) == false )
-                    {
-                        status &= 0xFD; // Datarate KO
-                    }
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-                    if( ( ValueInRange( datarate, DR_5, DR_7 ) == true ) ||
-                        ( datarate > DR_13 ) )
-                    {
-                        status &= 0xFD; // Datarate KO
-                    }
-#endif
-                    if( ValueInRange( drOffset, LORAMAC_MIN_RX1_DR_OFFSET, LORAMAC_MAX_RX1_DR_OFFSET ) == false )
-                    {
-                        status &= 0xFB; // Rx1DrOffset range KO
-                    }
-
-                    if( ( status & 0x07 ) == 0x07 )
-                    {
-                        Rx2Channel.Datarate = datarate;
-                        Rx2Channel.Frequency = freq;
-                        Rx1DrOffset = drOffset;
-                    }
-                    AddMacCommand( MOTE_MAC_RX_PARAM_SETUP_ANS, status, 0 );
-                }
-                break;
-            case SRV_MAC_DEV_STATUS_REQ:
-                {
-                    uint8_t batteryLevel = BAT_LEVEL_NO_MEASURE;
-                    if( ( LoRaMacCallbacks != NULL ) && ( LoRaMacCallbacks->GetBatteryLevel != NULL ) )
-                    {
-                        batteryLevel = LoRaMacCallbacks->GetBatteryLevel( );
-                    }
-                    AddMacCommand( MOTE_MAC_DEV_STATUS_ANS, batteryLevel, snr );
-                    break;
-                }
-            case SRV_MAC_NEW_CHANNEL_REQ:
-                {
-                    uint8_t status = 0x03;
-
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-                    status &= 0xFC; // Channel frequency and datarate KO
-                    macIndex += 5;
-#else
-                    int8_t channelIndex = 0;
-                    ChannelParams_t chParam;
-
-                    channelIndex = payload[macIndex++];
-                    chParam.Frequency = ( uint32_t )payload[macIndex++];
-                    chParam.Frequency |= ( uint32_t )payload[macIndex++] << 8;
-                    chParam.Frequency |= ( uint32_t )payload[macIndex++] << 16;
-                    chParam.Frequency *= 100;
-                    chParam.DrRange.Value = payload[macIndex++];
-
-                    LoRaMacState |= MAC_TX_CONFIG;
-                    if( chParam.Frequency == 0 )
-                    {
-                        if( channelIndex < 3 )
-                        {
-                            status &= 0xFC;
-                        }
-                        else
-                        {
-                            if( LoRaMacChannelRemove( channelIndex ) != LORAMAC_STATUS_OK )
-                            {
-                                status &= 0xFC;
-                            }
-                        }
-                    }
-                    else
-                    {
-                        switch( LoRaMacChannelAdd( channelIndex, chParam ) )
-                        {
-                            case LORAMAC_STATUS_OK:
-                            {
-                                break;
-                            }
-                            case LORAMAC_STATUS_FREQUENCY_INVALID:
-                            {
-                                status &= 0xFE;
-                                break;
-                            }
-                            case LORAMAC_STATUS_DATARATE_INVALID:
-                            {
-                                status &= 0xFD;
-                                break;
-                            }
-                            case LORAMAC_STATUS_FREQ_AND_DR_INVALID:
-                            {
-                                status &= 0xFC;
-                                break;
-                            }
-                            default:
-                            {
-                                status &= 0xFC;
-                                break;
-                            }
-                        }
-                    }
-                    LoRaMacState &= ~MAC_TX_CONFIG;
-#endif
-                    AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 );
-                }
-                break;
-            case SRV_MAC_RX_TIMING_SETUP_REQ:
-                {
-                    uint8_t delay = payload[macIndex++] & 0x0F;
-
-                    if( delay == 0 )
-                    {
-                        delay++;
-                    }
-                    ReceiveDelay1 = delay * 1e6;
-                    ReceiveDelay2 = ReceiveDelay1 + 1e6;
-                    AddMacCommand( MOTE_MAC_RX_TIMING_SETUP_ANS, 0, 0 );
-                }
-                break;
-            default:
-                // Unknown command. ABORT MAC commands processing
-                return;
-        }
-    }
-
-    // Process accumulated Link ADR channel mask changes
-    if( validLinkAdrCmds > 0 ) 
-    {
-        uint8_t drOkCounter = 0;
-        uint8_t status      = 0x07;
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-        for(uint8_t i=0; i< 6; i++)
-        {
-            for( uint8_t j = 0; j < 16; j++ )
-            {
-                if( ( channelsMask[i] & ( 1 << j ) ) != 0 ) 
-                {
-                    if ( ( Channels[i * 16 + j].Frequency == 0 ) )
-                    {
-                        status &= 0xFE; // Channel mask KO
-                        break;
-                    }
-                    else if( ( datarate >= Channels[i * 16 + j].DrRange.Fields.Min ) &&
-                             ( datarate <= Channels[i * 16 + j].DrRange.Fields.Max ) ) 
-                    {
-                        drOkCounter++;
-                    }
-                }
-            }
-        }
-
-        if ( drOkCounter == 0 )
-        {
-            status &= 0xFD;  // Datarate KO
-        }
-
-        if( ( CountNbEnabled125kHzChannels( channelsMask ) > 0 ) && ( CountNbEnabled125kHzChannels( channelsMask ) < HYBRD_CHNLS_MIN ) )
-        {
-            status &= 0xFE; // Channel mask KO
-        }
-
-#if defined( USE_BAND_915_HYBRID )
-        if( ValidateChannelMask( channelsMask ) == false )
-        {
-            status &= 0xFE; // Channel mask KO
-        }
-#endif
-
-#endif
-        if( ( status & 0x07 ) == 0x07 )
-        {
-            ChannelsDatarate = datarate;
-			ChannelsDefaultDatarate = datarate;
-            ChannelsTxPower = txPower;
-
-            ChannelsMask[0] = channelsMask[0];
-            ChannelsMask[1] = channelsMask[1];
-            ChannelsMask[2] = channelsMask[2];
-            ChannelsMask[3] = channelsMask[3];
-            ChannelsMask[4] = channelsMask[4];
-            ChannelsMask[5] = channelsMask[5];
-
-            ChannelsNbRep = nbRep; 
-            
-            // Clear remaining channels mask
-            memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, 10 );
-        }
-        // Channel Mask KO
-        else
-        {
-            // Update the last Link ADR status with channel mask KO
-            if( (LinkAdrMacCmdBufferIndex+1 ) < LORA_MAC_COMMAND_MAX_LENGTH )
-                MacCommandsBuffer[LinkAdrMacCmdBufferIndex+1] &= status;
-        }
-    }
-}
-
-LoRaMacStatus_t Send( LoRaMacHeader_t *macHdr, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    LoRaMacFrameCtrl_t fCtrl;
-    LoRaMacStatus_t status = LORAMAC_STATUS_PARAMETER_INVALID;
-
-    fCtrl.Value = 0;
-    fCtrl.Bits.FOptsLen      = 0;
-    fCtrl.Bits.FPending      = 0;
-    fCtrl.Bits.Ack           = false;
-    fCtrl.Bits.AdrAckReq     = false;
-    fCtrl.Bits.Adr           = AdrCtrlOn;
-
-    // Prepare the frame
-    status = PrepareFrame( macHdr, &fCtrl, fPort, fBuffer, fBufferSize );
-
-    // Validate status
-    if( status != LORAMAC_STATUS_OK )
-    {
-        return status;
-    }
-
-    // Reset confirm parameters
-    McpsConfirm.NbRetries = 0;
-    McpsConfirm.AckReceived = false;
-    McpsConfirm.UpLinkCounter = UpLinkCounter;
-
-    status = ScheduleTx( );
-
-    return status;
-}
-
-static LoRaMacStatus_t ScheduleTx( )
-{
-    TimerTime_t dutyCycleTimeOff = 0;
-
-    // Check if the device is off
-    if( MaxDCycle == 255 )
-    {
-        return LORAMAC_STATUS_DEVICE_OFF;
-    }
-    if( MaxDCycle == 0 )
-    {
-        AggregatedTimeOff = 0;
-    }
-
-    CalculateBackOff( LastTxChannel );
-
-    // Select channel
-    while( SetNextChannel( &dutyCycleTimeOff ) == false )
-    {
-        // Set the default datarate
-        ChannelsDatarate = ChannelsDefaultDatarate;
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-        // Re-enable default channels LC1, LC2, LC3
-        ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
-#endif
-    }
-
-    // Schedule transmission of frame
-    if( dutyCycleTimeOff == 0 )
-    {
-        // Try to send now
-        return SendFrameOnChannel( Channels[Channel] );
-    }
-    else
-    {
-        // Send later - prepare timer
-        LoRaMacState |= MAC_TX_DELAYED;
-        TimerSetValue( &TxDelayedTimer, dutyCycleTimeOff );
-        TimerStart( &TxDelayedTimer );
-
-        return LORAMAC_STATUS_OK;
-    }
-}
-
-static void CalculateBackOff( uint8_t channel )
-{
-    uint16_t dutyCycle = Bands[Channels[channel].Band].DCycle;
-
-    if( IsLoRaMacNetworkJoined == false )
-    {
-#if defined( USE_BAND_868 ) || defined( USE_BAND_433 ) || defined( USE_BAND_780 )
-        dutyCycle = JOIN_DC;
-#endif
-    }
-
-    // Update Band Time OFF
-    if( DutyCycleOn == true )
-    {
-        Bands[Channels[channel].Band].TimeOff = TxTimeOnAir * dutyCycle - TxTimeOnAir;
-    }
-    else
-    {
-        Bands[Channels[channel].Band].TimeOff = 0;
-    }
-    // Update Aggregated Time OFF
-    AggregatedTimeOff = AggregatedTimeOff + ( TxTimeOnAir * AggregatedDCycle - TxTimeOnAir );
-}
-
-LoRaMacStatus_t PrepareFrame( LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t fPort, void *fBuffer, uint16_t fBufferSize )
-{
-    uint16_t i;
-    uint8_t pktHeaderLen = 0;
-    uint32_t mic = 0;
-    const void* payload = fBuffer;
-    uint8_t payloadSize = fBufferSize;
-    uint8_t framePort = fPort;
-
-    LoRaMacBufferPktLen = 0;
-
-    NodeAckRequested = false;
-
-    if( fBuffer == NULL )
-    {
-        fBufferSize = 0;
-    }
-
-    LoRaMacBuffer[pktHeaderLen++] = macHdr->Value;
-
-    switch( macHdr->Bits.MType )
-    {
-        case FRAME_TYPE_JOIN_REQ:
-            RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME;
-            RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME;
-
-            LoRaMacBufferPktLen = pktHeaderLen;
-
-            memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacAppEui, 8 );
-            LoRaMacBufferPktLen += 8;
-            memcpyr( LoRaMacBuffer + LoRaMacBufferPktLen, LoRaMacDevEui, 8 );
-            LoRaMacBufferPktLen += 8;
-
-            LoRaMacDevNonce = Radio.Random( );
-
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = LoRaMacDevNonce & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( LoRaMacDevNonce >> 8 ) & 0xFF;
-
-            LoRaMacJoinComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen & 0xFF, LoRaMacAppKey, &mic );
-
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = mic & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 8 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 16 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen++] = ( mic >> 24 ) & 0xFF;
-
-            break;
-        case FRAME_TYPE_DATA_CONFIRMED_UP:
-            NodeAckRequested = true;
-            //Intentional falltrough
-        case FRAME_TYPE_DATA_UNCONFIRMED_UP:
-            if( IsLoRaMacNetworkJoined == false )
-            {
-                return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
-            }
-
-            fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate, &ChannelsTxPower );
-
-            if( ValidatePayloadLength( fBufferSize, ChannelsDatarate, MacCommandsBufferIndex ) == false )
-            {
-                return LORAMAC_STATUS_LENGTH_ERROR;
-            }
-
-            RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME;
-            RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME;
-
-            if( SrvAckRequested == true )
-            {
-                SrvAckRequested = false;
-                fCtrl->Bits.Ack = 1;
-            }
-
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr ) & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 8 ) & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 16 ) & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( LoRaMacDevAddr >> 24 ) & 0xFF;
-
-            LoRaMacBuffer[pktHeaderLen++] = fCtrl->Value;
-
-            LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
-            LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
-
-            // Copy the MAC commands which must be re-send into the MAC command buffer
-            memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
-            MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
-
-            if( ( payload != NULL ) && ( payloadSize > 0 ) )
-            {
-                if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
-                {
-                    fCtrl->Bits.FOptsLen += MacCommandsBufferIndex;
-
-                    // Update FCtrl field with new value of OptionsLength
-                    LoRaMacBuffer[0x05] = fCtrl->Value;
-                    for( i = 0; i < MacCommandsBufferIndex; i++ )
-                    {
-                        LoRaMacBuffer[pktHeaderLen++] = MacCommandsBuffer[i];
-                    }
-                }
-            }
-            else
-            {
-                if( ( MacCommandsBufferIndex > 0 ) && ( MacCommandsInNextTx ) )
-                {
-                    payloadSize = MacCommandsBufferIndex;
-                    payload = MacCommandsBuffer;
-                    framePort = 0;
-                }
-            }
-            MacCommandsInNextTx = false;
-            // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
-            MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat );
-            if( MacCommandsBufferToRepeatIndex > 0 )
-            {
-                MacCommandsInNextTx = true;
-            }
-            MacCommandsBufferIndex = 0;
-
-            if( ( payload != NULL ) && ( payloadSize > 0 ) )
-            {
-                LoRaMacBuffer[pktHeaderLen++] = framePort;
-
-                if( framePort == 0 )
-                {
-                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
-                }
-                else
-                {
-                    LoRaMacPayloadEncrypt( (uint8_t* ) payload, payloadSize, LoRaMacAppSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, LoRaMacPayload );
-                }
-                memcpy1( LoRaMacBuffer + pktHeaderLen, LoRaMacPayload, payloadSize );
-            }
-            LoRaMacBufferPktLen = pktHeaderLen + payloadSize;
-
-            LoRaMacComputeMic( LoRaMacBuffer, LoRaMacBufferPktLen, LoRaMacNwkSKey, LoRaMacDevAddr, UP_LINK, UpLinkCounter, &mic );
-
-            LoRaMacBuffer[LoRaMacBufferPktLen + 0] = mic & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen + 1] = ( mic >> 8 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen + 2] = ( mic >> 16 ) & 0xFF;
-            LoRaMacBuffer[LoRaMacBufferPktLen + 3] = ( mic >> 24 ) & 0xFF;
-
-            LoRaMacBufferPktLen += LORAMAC_MFR_LEN;
-
-            break;
-        case FRAME_TYPE_PROPRIETARY:
-            if( ( fBuffer != NULL ) && ( fBufferSize > 0 ) )
-            {
-                memcpy1( LoRaMacBuffer + pktHeaderLen, ( uint8_t* ) fBuffer, fBufferSize );
-                LoRaMacBufferPktLen = pktHeaderLen + fBufferSize;
-            }
-            break;
-        default:
-            return LORAMAC_STATUS_SERVICE_UNKNOWN;
-    }
-
-    return LORAMAC_STATUS_OK;
-}
-
-LoRaMacStatus_t SendFrameOnChannel( ChannelParams_t channel )
-{
-    int8_t datarate = Datarates[ChannelsDatarate];
-    int8_t txPowerIndex = 0;
-    int8_t txPower = 0;
-
-    txPowerIndex = LimitTxPower( ChannelsTxPower );
-    txPower = TxPowers[txPowerIndex];
-
-    MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-    McpsConfirm.Datarate = ChannelsDatarate;
-    McpsConfirm.TxPower = txPowerIndex;
-
-    Radio.SetChannel( channel.Frequency );
-    
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( ChannelsDatarate == DR_7 )
-    { // High Speed FSK channel
-        Radio.SetMaxPayloadLength( MODEM_FSK, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_FSK, txPower, 25e3, 0, datarate * 1e3, 0, 5, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_FSK, LoRaMacBufferPktLen );
-
-    }
-    else if( ChannelsDatarate == DR_6 )
-    { // High speed LoRa channel
-        Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 1, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-    else
-    { // Normal LoRa channel
-        Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    Radio.SetMaxPayloadLength( MODEM_LORA, LoRaMacBufferPktLen );
-    if( ChannelsDatarate >= DR_4 )
-    { // High speed LoRa channel BW500 kHz
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 2, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-    else
-    { // Normal LoRa channel
-        Radio.SetTxConfig( MODEM_LORA, txPower, 0, 0, datarate, 1, 8, false, true, 0, 0, false, 3e6 );
-        TxTimeOnAir = Radio.TimeOnAir( MODEM_LORA, LoRaMacBufferPktLen );
-    }
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-
-    // Store the time on air
-    McpsConfirm.TxTimeOnAir = TxTimeOnAir;
-    MlmeConfirm.TxTimeOnAir = TxTimeOnAir;
-
-    // Starts the MAC layer status check timer
-    TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
-    TimerStart( &MacStateCheckTimer );
-
-    // Send now
-    Radio.Send( LoRaMacBuffer, LoRaMacBufferPktLen );
-
-    LoRaMacState |= MAC_TX_RUNNING;
-
-    return LORAMAC_STATUS_OK;
-}
-
-
-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks )
-{
-    if( primitives == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    if( ( primitives->MacMcpsConfirm == NULL ) ||
-        ( primitives->MacMcpsIndication == NULL ) ||
-        ( primitives->MacMlmeConfirm == NULL ))
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    LoRaMacPrimitives = primitives;
-    LoRaMacCallbacks = callbacks;
-
-    LoRaMacFlags.Value = 0;
-
-    LoRaMacDeviceClass = CLASS_A;
-
-    UpLinkCounter = 1;
-    DownLinkCounter = 0;
-    AdrAckCounter = 0;
-
-    ChannelsNbRepCounter = 0;
-
-    AckTimeoutRetries = 1;
-    AckTimeoutRetriesCounter = 1;
-    AckTimeoutRetry = false;
-
-    MaxDCycle = 0;
-    AggregatedDCycle = 1;
-
-    MacCommandsBufferIndex = 0;
-    MacCommandsBufferToRepeatIndex = 0;
-
-    IsRxWindowsEnabled = true;
-
-    RepeaterSupport = false;
-    IsRxWindowsEnabled = true;
-    IsLoRaMacNetworkJoined = false;
-    LoRaMacState = MAC_IDLE;
-
-    NodeAckRequested = false;
-    SrvAckRequested = false;
-    MacCommandsInNextTx = false;
-
-#if defined( USE_BAND_433 )
-    ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
-#elif defined( USE_BAND_780 )
-    ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
-#elif defined( USE_BAND_868 )
-    ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
-#elif defined( USE_BAND_915 )
-    ChannelsMask[0] = 0xFFFF;
-    ChannelsMask[1] = 0xFFFF;
-    ChannelsMask[2] = 0xFFFF;
-    ChannelsMask[3] = 0xFFFF;
-    ChannelsMask[4] = 0x00FF;
-    ChannelsMask[5] = 0x0000;
-
-    memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );
-#elif defined( USE_BAND_915_HYBRID )
-    ChannelsMask[0] = 0x00FF;
-    ChannelsMask[1] = 0x0000;
-    ChannelsMask[2] = 0x0000;
-    ChannelsMask[3] = 0x0000;
-    ChannelsMask[4] = 0x0001;
-    ChannelsMask[5] = 0x0000;
-
-    memcpy1( ( uint8_t* ) ChannelsMaskRemaining, ( uint8_t* ) ChannelsMask, sizeof( ChannelsMask ) );
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    // 125 kHz channels
-    for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ )
-    {
-        Channels[i].Frequency = 902.3e6 + i * 200e3;
-        Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0;
-        Channels[i].Band = 0;
-    }
-    // 500 kHz channels
-    for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ )
-    {
-        Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6;
-        Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4;
-        Channels[i].Band = 0;
-    }
-#endif
-
-    ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
-    ChannelsDefaultDatarate = ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
-    ChannelsNbRep = 1;
-    ChannelsNbRepCounter = 0;
-
-	Rx2Channel.Frequency = 923300000;
-    Rx2Channel.Datarate = DR_8;
-    Rx1DrOffset = 0;
-
-
-    MaxDCycle = 0;
-    AggregatedDCycle = 1;
-    AggregatedLastTxDoneTime = 0;
-    AggregatedTimeOff = 0;
-
-#if defined( USE_BAND_433 )
-    DutyCycleOn = false;
-#elif defined( USE_BAND_780 )
-    DutyCycleOn = false;
-#elif defined( USE_BAND_868 )
-    DutyCycleOn = true;
-#elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-    DutyCycleOn = false;
-#else
-    #error "Please define a frequency band in the compiler options."
-#endif
-
-    MaxRxWindow = MAX_RX_WINDOW;
-    ReceiveDelay1 = RECEIVE_DELAY1;
-    ReceiveDelay2 = RECEIVE_DELAY2;
-    JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1;
-    JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2;
-
-#if defined( USE_BAND_915 ) 
-    NextJoinBlock = 0;
-    LastJoinBlock = -1;
-    JoinBlocksRemaining = 0xff;
-    Join500KHzRemaining = 0xff;
-#endif
-
-    LastJoinTxTime  = 0;
-    JoinAggTimeOnAir = 0; 
-
-    TimerInit( &MacStateCheckTimer, OnMacStateCheckTimerEvent );
-    TimerSetValue( &MacStateCheckTimer, MAC_STATE_CHECK_TIMEOUT );
-
-    TimerInit( &TxDelayedTimer, OnTxDelayedTimerEvent );
-    TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent );
-    TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent );
-    TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent );
-
-    // Initialize Radio driver
-    RadioEvents.TxDone = OnRadioTxDone;
-    RadioEvents.RxDone = OnRadioRxDone;
-    RadioEvents.RxError = OnRadioRxError;
-    RadioEvents.TxTimeout = OnRadioTxTimeout;
-    RadioEvents.RxTimeout = OnRadioRxTimeout;
-    Radio.Init( &RadioEvents );
-
-    // Random seed initialization
-    srand1( Radio.Random( ) );
-
-    // Initialize channel index.
-    Channel = LORA_MAX_NB_CHANNELS;
-
-    PublicNetwork = true;
-    SetPublicNetwork( PublicNetwork );
-    Radio.Sleep( );
-
-    return LORAMAC_STATUS_OK;
-}
-
-LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
-{
-    int8_t  datarate = ChannelsDefaultDatarate;
-    uint8_t fOptLen  = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
-
-    if( txInfo == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    AdrNextDr( AdrCtrlOn, false, &datarate, NULL );
-
-    if( RepeaterSupport == true )
-    {
-        txInfo->CurrentPayloadSize = MaxPayloadOfDatarateRepeater[datarate];
-    }
-    else
-    {
-        txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
-    }
-
-    if( txInfo->CurrentPayloadSize >= fOptLen )
-    {
-        txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
-    }
-    else
-    {
-        return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
-    }
-
-    if( ValidatePayloadLength( size, datarate, 0 ) == false )
-    {
-        return LORAMAC_STATUS_LENGTH_ERROR;
-    }
-
-    if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
-    {
-        return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
-    }
-
-    return LORAMAC_STATUS_OK;
-}
-
-LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_OK;
-
-    if( mibGet == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-
-    switch( mibGet->Type )
-    {
-        case MIB_DEVICE_CLASS:
-        {
-            mibGet->Param.Class = LoRaMacDeviceClass;
-            break;
-        }
-        case MIB_NETWORK_JOINED:
-        {
-            mibGet->Param.IsNetworkJoined = IsLoRaMacNetworkJoined;
-            break;
-        }
-        case MIB_ADR:
-        {
-            mibGet->Param.AdrEnable = AdrCtrlOn;
-            break;
-        }
-        case MIB_NET_ID:
-        {
-            mibGet->Param.NetID = LoRaMacNetID;
-            break;
-        }
-        case MIB_DEV_ADDR:
-        {
-            mibGet->Param.DevAddr = LoRaMacDevAddr;
-            break;
-        }
-        case MIB_NWK_SKEY:
-        {
-            mibGet->Param.NwkSKey = LoRaMacNwkSKey;
-            break;
-        }
-        case MIB_APP_SKEY:
-        {
-            mibGet->Param.AppSKey = LoRaMacAppSKey;
-            break;
-        }
-        case MIB_PUBLIC_NETWORK:
-        {
-            mibGet->Param.EnablePublicNetwork = PublicNetwork;
-            break;
-        }
-        case MIB_REPEATER_SUPPORT:
-        {
-            mibGet->Param.EnableRepeaterSupport = RepeaterSupport;
-            break;
-        }
-        case MIB_CHANNELS:
-        {
-            mibGet->Param.ChannelList = Channels;
-            break;
-        }
-        case MIB_RX2_CHANNEL:
-        {
-            mibGet->Param.Rx2Channel = Rx2Channel;
-            break;
-        }
-        case MIB_CHANNELS_MASK:
-        {
-            mibGet->Param.ChannelsMask = ChannelsMask;
-            break;
-        }
-        case MIB_CHANNELS_NB_REP:
-        {
-            mibGet->Param.ChannelNbRep = ChannelsNbRep;
-            break;
-        }
-        case MIB_MAX_RX_WINDOW_DURATION:
-        {
-            mibGet->Param.MaxRxWindow = MaxRxWindow;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_1:
-        {
-            mibGet->Param.ReceiveDelay1 = ReceiveDelay1;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_2:
-        {
-            mibGet->Param.ReceiveDelay2 = ReceiveDelay2;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_1:
-        {
-            mibGet->Param.JoinAcceptDelay1 = JoinAcceptDelay1;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_2:
-        {
-            mibGet->Param.JoinAcceptDelay2 = JoinAcceptDelay2;
-            break;
-        }
-        case MIB_CHANNELS_DEFAULT_DATARATE:
-        {
-            mibGet->Param.ChannelsDefaultDatarate = ChannelsDefaultDatarate;
-            break;
-        }
-        case MIB_CHANNELS_DATARATE:
-        {
-            mibGet->Param.ChannelsDatarate = ChannelsDatarate;
-            break;
-        }
-        case MIB_CHANNELS_TX_POWER:
-        {
-            mibGet->Param.ChannelsTxPower = ChannelsTxPower;
-            break;
-        }
-        case MIB_UPLINK_COUNTER:
-        {
-            mibGet->Param.UpLinkCounter = UpLinkCounter;
-            break;
-        }
-        case MIB_DOWNLINK_COUNTER:
-        {
-            mibGet->Param.DownLinkCounter = DownLinkCounter;
-            break;
-        }
-        case MIB_MULTICAST_CHANNEL:
-        {
-            mibGet->Param.MulticastList = MulticastChannels;
-            break;
-        }
-        default:
-            status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-            break;
-    }
-
-    return status;
-}
-
-LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_OK;
-
-    if( mibSet == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    switch( mibSet->Type )
-    {
-        case MIB_DEVICE_CLASS:
-        {
-            LoRaMacDeviceClass = mibSet->Param.Class;
-            switch( LoRaMacDeviceClass )
-            {
-                case CLASS_A:
-                {
-                    // Set the radio into sleep to setup a defined state
-                    Radio.Sleep( );
-                    break;
-                }
-                case CLASS_B:
-                {
-                    break;
-                }
-                case CLASS_C:
-                {
-                    // Set the NodeAckRequested indicator to default
-                    NodeAckRequested = false;
-                    OnRxWindow2TimerEvent( );
-                    break;
-                }
-            }
-            break;
-        }
-        case MIB_NETWORK_JOINED:
-        {
-            IsLoRaMacNetworkJoined = mibSet->Param.IsNetworkJoined;
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-            if( IsLoRaMacNetworkJoined == false )
-            {
-                NextJoinBlock = 0;
-                JoinBlocksRemaining = 0xff;
-                Join500KHzRemaining = 0xff;
-            }
-#endif
-            break;
-        }
-        case MIB_ADR:
-        {
-            AdrCtrlOn = mibSet->Param.AdrEnable;
-            break;
-        }
-        case MIB_NET_ID:
-        {
-            LoRaMacNetID = mibSet->Param.NetID;
-            break;
-        }
-        case MIB_DEV_ADDR:
-        {
-            LoRaMacDevAddr = mibSet->Param.DevAddr;
-            break;
-        }
-        case MIB_NWK_SKEY:
-        {
-            if( mibSet->Param.NwkSKey != NULL )
-            {
-                memcpy1( LoRaMacNwkSKey, mibSet->Param.NwkSKey,
-                               sizeof( LoRaMacNwkSKey ) );
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_APP_SKEY:
-        {
-            if( mibSet->Param.AppSKey != NULL )
-            {
-                memcpy1( LoRaMacAppSKey, mibSet->Param.AppSKey,
-                               sizeof( LoRaMacAppSKey ) );
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_PUBLIC_NETWORK:
-        {
-            SetPublicNetwork( mibSet->Param.EnablePublicNetwork );
-            break;
-        }
-        case MIB_REPEATER_SUPPORT:
-        {
-             RepeaterSupport = mibSet->Param.EnableRepeaterSupport;
-            break;
-        }
-        case MIB_RX2_CHANNEL:
-        {
-            Rx2Channel = mibSet->Param.Rx2Channel;
-            break;
-        }
-        case MIB_CHANNELS_MASK:
-        {
-            if( mibSet->Param.ChannelsMask )
-            {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                bool chanMaskState = true;
-
-#if defined( USE_BAND_915_HYBRID )
-                chanMaskState = ValidateChannelMask( mibSet->Param.ChannelsMask );
-#endif
-                if( chanMaskState == true )
-                {
-                    if( ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) < HYBRD_CHNLS_MIN ) &&
-                        ( CountNbEnabled125kHzChannels( mibSet->Param.ChannelsMask ) > 0 ) )
-                    {
-                        status = LORAMAC_STATUS_PARAMETER_INVALID;
-                    }
-                    else
-                    {
-                        memcpy1( ( uint8_t* ) ChannelsMask,
-                                 ( uint8_t* ) mibSet->Param.ChannelsMask, sizeof( ChannelsMask ) );
-                        for ( uint8_t i = 0; i < sizeof( ChannelsMask ) / 2; i++ )
-                        {
-                            // Disable channels which are no longer available
-                            ChannelsMaskRemaining[i] &= ChannelsMask[i];
-                        }
-                    }
-                }
-                else
-                {
-                    status = LORAMAC_STATUS_PARAMETER_INVALID;
-                }
-#else
-                memcpy1( ( uint8_t* ) ChannelsMask,
-                         ( uint8_t* ) mibSet->Param.ChannelsMask, 2 );
-#endif
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_CHANNELS_NB_REP:
-        {
-            if( ( mibSet->Param.ChannelNbRep >= 1 ) &&
-                ( mibSet->Param.ChannelNbRep <= 15 ) )
-            {
-                ChannelsNbRep = mibSet->Param.ChannelNbRep;
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_MAX_RX_WINDOW_DURATION:
-        {
-            MaxRxWindow = mibSet->Param.MaxRxWindow;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_1:
-        {
-            ReceiveDelay1 = mibSet->Param.ReceiveDelay1;
-            break;
-        }
-        case MIB_RECEIVE_DELAY_2:
-        {
-            ReceiveDelay2 = mibSet->Param.ReceiveDelay2;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_1:
-        {
-            JoinAcceptDelay1 = mibSet->Param.JoinAcceptDelay1;
-            break;
-        }
-        case MIB_JOIN_ACCEPT_DELAY_2:
-        {
-            JoinAcceptDelay2 = mibSet->Param.JoinAcceptDelay2;
-            break;
-        }
-        case MIB_CHANNELS_DEFAULT_DATARATE:
-        {
-            if( ValueInRange( mibSet->Param.ChannelsDefaultDatarate,
-                              LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
-            {
-                ChannelsDefaultDatarate = mibSet->Param.ChannelsDefaultDatarate;
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_CHANNELS_DATARATE:
-        {
-            if( ValueInRange( mibSet->Param.ChannelsDatarate,
-                              LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) )
-            {
-                ChannelsDatarate = mibSet->Param.ChannelsDatarate;
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_CHANNELS_TX_POWER:
-        {
-            if( ValueInRange( mibSet->Param.ChannelsTxPower,
-                              LORAMAC_MAX_TX_POWER, LORAMAC_MIN_TX_POWER ) )
-            {
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-                int8_t txPower = LimitTxPower( mibSet->Param.ChannelsTxPower );
-                if( txPower == mibSet->Param.ChannelsTxPower )
-                {
-                    ChannelsTxPower = mibSet->Param.ChannelsTxPower;
-                }
-                else
-                {
-                    status = LORAMAC_STATUS_PARAMETER_INVALID;
-                }
-#else
-                ChannelsTxPower = mibSet->Param.ChannelsTxPower;
-#endif
-            }
-            else
-            {
-                status = LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-            break;
-        }
-        case MIB_UPLINK_COUNTER:
-        {
-            UpLinkCounter = mibSet->Param.UpLinkCounter;
-            break;
-        }
-        case MIB_DOWNLINK_COUNTER:
-        {
-            DownLinkCounter = mibSet->Param.DownLinkCounter;
-            break;
-        }
-        default:
-            status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-            break;
-    }
-
-    return status;
-}
-
-LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params )
-{
-#if ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    return LORAMAC_STATUS_PARAMETER_INVALID;
-#else
-    bool datarateInvalid = false;
-    bool frequencyInvalid = false;
-    uint8_t band = 0;
-
-    // The id must not exceed LORA_MAX_NB_CHANNELS
-    if( id >= LORA_MAX_NB_CHANNELS )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    // Validate if the MAC is in a correct state
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
-        {
-            return LORAMAC_STATUS_BUSY;
-        }
-    }
-    // Validate the datarate
-    if( ( params.DrRange.Fields.Min > params.DrRange.Fields.Max ) ||
-        ( ValueInRange( params.DrRange.Fields.Min, LORAMAC_TX_MIN_DATARATE,
-                        LORAMAC_TX_MAX_DATARATE ) == false ) ||
-        ( ValueInRange( params.DrRange.Fields.Max, LORAMAC_TX_MIN_DATARATE,
-                        LORAMAC_TX_MAX_DATARATE ) == false ) )
-    {
-        datarateInvalid = true;
-    }
-
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( id < 3 )
-    {
-        if( params.Frequency != Channels[id].Frequency )
-        {
-            frequencyInvalid = true;
-        }
-
-        if( params.DrRange.Fields.Min > ChannelsDefaultDatarate )
-        {
-            datarateInvalid = true;
-        }
-        if( ValueInRange( params.DrRange.Fields.Max, DR_5, LORAMAC_TX_MAX_DATARATE ) == false )
-        {
-            datarateInvalid = true;
-        }
-    }
-#endif
-
-    // Validate the frequency
-    if( ( Radio.CheckRfFrequency( params.Frequency ) == true ) && ( params.Frequency > 0 ) && ( frequencyInvalid == false ) )
-    {
-#if defined( USE_BAND_868 )
-        if( ( params.Frequency >= 865000000 ) && ( params.Frequency <= 868000000 ) )
-        {
-            band = BAND_G1_0;
-        }
-        else if( ( params.Frequency > 868000000 ) && ( params.Frequency <= 868600000 ) )
-        {
-            band = BAND_G1_1;
-        }
-        else if( ( params.Frequency >= 868700000 ) && ( params.Frequency <= 869200000 ) )
-        {
-            band = BAND_G1_2;
-        }
-        else if( ( params.Frequency >= 869400000 ) && ( params.Frequency <= 869650000 ) )
-        {
-            band = BAND_G1_3;
-        }
-        else if( ( params.Frequency >= 869700000 ) && ( params.Frequency <= 870000000 ) )
-        {
-            band = BAND_G1_4;
-        }
-        else
-        {
-            frequencyInvalid = true;
-        }
-#endif
-    }
-    else
-    {
-        frequencyInvalid = true;
-    }
-
-    if( ( datarateInvalid == true ) && ( frequencyInvalid == true ) )
-    {
-        return LORAMAC_STATUS_FREQ_AND_DR_INVALID;
-    }
-    if( datarateInvalid == true )
-    {
-        return LORAMAC_STATUS_DATARATE_INVALID;
-    }
-    if( frequencyInvalid == true )
-    {
-        return LORAMAC_STATUS_FREQUENCY_INVALID;
-    }
-
-    // Every parameter is valid, activate the channel
-    Channels[id] = params;
-    Channels[id].Band = band;
-    ChannelsMask[0] |= ( 1 << id );
-
-    return LORAMAC_STATUS_OK;
-#endif
-}
-
-LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id )
-{
-#if defined( USE_BAND_433 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 )
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        if( ( LoRaMacState & MAC_TX_CONFIG ) != MAC_TX_CONFIG )
-        {
-            return LORAMAC_STATUS_BUSY;
-        }
-    }
-
-    if( ( id < 3 ) || ( id >= LORA_MAX_NB_CHANNELS ) )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    else
-    {
-        // Remove the channel from the list of channels
-        Channels[id] = ( ChannelParams_t ){ 0, { 0 }, 0 };
-
-        // Disable the channel as it doesn't exist anymore
-        if( DisableChannelInMask( id, ChannelsMask ) == false )
-        {
-            return LORAMAC_STATUS_PARAMETER_INVALID;
-        }
-    }
-    return LORAMAC_STATUS_OK;
-#elif ( defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) )
-    return LORAMAC_STATUS_PARAMETER_INVALID;
-#endif
-}
-
-LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam )
-{
-    if( channelParam == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    // Reset downlink counter
-    channelParam->DownLinkCounter = 0;
-
-    if( MulticastChannels == NULL )
-    {
-        // New node is the fist element
-        MulticastChannels = channelParam;
-    }
-    else
-    {
-        MulticastParams_t *cur = MulticastChannels;
-
-        // Search the last node in the list
-        while( cur->Next != NULL )
-        {
-            cur = cur->Next;
-        }
-        // This function always finds the last node
-        cur->Next = channelParam;
-    }
-
-    return LORAMAC_STATUS_OK;
-}
-
-LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam )
-{
-    if( channelParam == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    if( MulticastChannels != NULL )
-    {
-        if( MulticastChannels == channelParam )
-        {
-          // First element
-          MulticastChannels = channelParam->Next;
-        }
-        else
-        {
-            MulticastParams_t *cur = MulticastChannels;
-
-            // Search the node in the list
-            while( cur->Next && cur->Next != channelParam )
-            {
-                cur = cur->Next;
-            }
-            // If we found the node, remove it
-            if( cur->Next )
-            {
-                cur->Next = channelParam->Next;
-            }
-        }
-        channelParam->Next = NULL;
-    }
-
-    return LORAMAC_STATUS_OK;
-}
-
-LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-    LoRaMacHeader_t macHdr;
-
-    if( mlmeRequest == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    memset1( ( uint8_t* ) &MlmeConfirm, 0, sizeof( MlmeConfirm ) );
-
-    MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-
-    switch( mlmeRequest->Type )
-    {
-        case MLME_JOIN:
-        {
-            if( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED )
-            {
-                return LORAMAC_STATUS_BUSY;
-            }
-
-            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
-            if( ( mlmeRequest->Req.Join.DevEui == NULL ) ||
-                ( mlmeRequest->Req.Join.AppEui == NULL ) ||
-                ( mlmeRequest->Req.Join.AppKey == NULL ) )
-            {
-                return LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-
-            LoRaMacFlags.Bits.MlmeReq = 1;
-
-            LoRaMacDevEui = mlmeRequest->Req.Join.DevEui;
-            LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
-            LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
-
-// Disable join retransmission dutycycle as it does not currently 
-// handle device reset 
-#if 0
-            if( LoRaMacCalcJoinBackOff( ) != 0 )
-            {
-                return LORAMAC_STATUS_TX_DCYCLE_EXCEEDED;
-            }
-#endif
-
-            macHdr.Value = 0;
-            macHdr.Bits.MType  = FRAME_TYPE_JOIN_REQ;
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-            if ( IsLoRaMacNetworkJoined == true )
-            {
-                NextJoinBlock = 0;
-                JoinBlocksRemaining = 0xff;
-                Join500KHzRemaining = 0xff;
-                IsLoRaMacNetworkJoined = false;
-            }
-#endif
-
-#if defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID )
-#if defined( USE_BAND_915 )
-            // Re-enable 500 kHz default channels
-            ChannelsMask[4] = 0x00FF;
-#else // defined( USE_BAND_915_HYBRID )
-            // Re-enable 500 kHz default channels
-            ChannelsMask[4] = 0x0001;
-#endif
-
-            static uint8_t drSwitch = 0;
-
-            if( ( ++drSwitch & 0x01 ) == 0x01 )
-            {
-                ChannelsDatarate = DR_0;
-            }
-            else
-            {
-                ChannelsDatarate = DR_4;
-            }
-#endif
-
-            status = Send( &macHdr, 0, NULL, 0 );
-            break;
-        }
-        case MLME_LINK_CHECK:
-        {
-            LoRaMacFlags.Bits.MlmeReq = 1;
-            // LoRaMac will send this command piggy-pack
-            MlmeConfirm.MlmeRequest = mlmeRequest->Type;
-
-            status = AddMacCommand( MOTE_MAC_LINK_CHECK_REQ, 0, 0 );
-            break;
-        }
-        default:
-            break;
-    }
-
-    if( status != LORAMAC_STATUS_OK )
-    {
-        NodeAckRequested = false;
-        LoRaMacFlags.Bits.MlmeReq = 0;
-    }
-
-    return status;
-}
-
-LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest )
-{
-    LoRaMacStatus_t status = LORAMAC_STATUS_SERVICE_UNKNOWN;
-    LoRaMacHeader_t macHdr;
-    uint8_t fPort = 0;
-    void *fBuffer;
-    uint16_t fBufferSize;
-    int8_t datarate;
-    bool readyToSend = false;
-
-    if( mcpsRequest == NULL )
-    {
-        return LORAMAC_STATUS_PARAMETER_INVALID;
-    }
-    if( ( ( LoRaMacState & MAC_TX_RUNNING ) == MAC_TX_RUNNING ) ||
-        ( ( LoRaMacState & MAC_TX_DELAYED ) == MAC_TX_DELAYED ) )
-    {
-        return LORAMAC_STATUS_BUSY;
-    }
-
-    macHdr.Value = 0;
-    memset1 ( ( uint8_t* ) &McpsConfirm, 0, sizeof( McpsConfirm ) );
-    McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_ERROR;
-
-    switch( mcpsRequest->Type )
-    {
-        case MCPS_UNCONFIRMED:
-        {
-            readyToSend = true;
-            AckTimeoutRetries = 1;
-
-            macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP;
-            fPort = mcpsRequest->Req.Unconfirmed.fPort;
-            fBuffer = mcpsRequest->Req.Unconfirmed.fBuffer;
-            fBufferSize = mcpsRequest->Req.Unconfirmed.fBufferSize;
-            datarate = mcpsRequest->Req.Unconfirmed.Datarate;
-            break;
-        }
-        case MCPS_CONFIRMED:
-        {
-            readyToSend = true;
-            AckTimeoutRetriesCounter = 1;
-            AckTimeoutRetries = mcpsRequest->Req.Confirmed.NbTrials;
-
-            macHdr.Bits.MType = FRAME_TYPE_DATA_CONFIRMED_UP;
-            fPort = mcpsRequest->Req.Confirmed.fPort;
-            fBuffer = mcpsRequest->Req.Confirmed.fBuffer;
-            fBufferSize = mcpsRequest->Req.Confirmed.fBufferSize;
-            datarate = mcpsRequest->Req.Confirmed.Datarate;
-            break;
-        }
-        case MCPS_PROPRIETARY:
-        {
-            readyToSend = true;
-            AckTimeoutRetries = 1;
-
-            macHdr.Bits.MType = FRAME_TYPE_PROPRIETARY;
-            fBuffer = mcpsRequest->Req.Proprietary.fBuffer;
-            fBufferSize = mcpsRequest->Req.Proprietary.fBufferSize;
-            datarate = mcpsRequest->Req.Proprietary.Datarate;
-            break;
-        }
-        default:
-            break;
-    }
-
-    if( readyToSend == true )
-    {
-        if( AdrCtrlOn == false )
-        {
-            if( ValueInRange( datarate, LORAMAC_TX_MIN_DATARATE, LORAMAC_TX_MAX_DATARATE ) == true )
-            {
-                ChannelsDatarate = datarate;
-            }
-            else
-            {
-                return LORAMAC_STATUS_PARAMETER_INVALID;
-            }
-        }
-
-        status = Send( &macHdr, fPort, fBuffer, fBufferSize );
-        if( status == LORAMAC_STATUS_OK )
-        {
-            McpsConfirm.McpsRequest = mcpsRequest->Type;
-            LoRaMacFlags.Bits.McpsReq = 1;
-        }
-        else
-        {
-            NodeAckRequested = false;
-        }
-    }
-
-    return status;
-}
-
-TimerTime_t LoRaMacCalcJoinBackOff( )
-{
-    TimerTime_t timeOff = 0; 
-    TimerTime_t uptime; 
-    TimerTime_t currDCycleEndTime;
-    TimerTime_t prevDCycleEndTime; 
-    TimerTime_t period;
-    TimerTime_t onAirTimeMax;
-    TimerTime_t lastJoinTime;
-    TimerTime_t elapsedTime;
-    uint8_t     dcyclePeriod;
-
-    // Check retransmit duty-cycle is enabled 
-    if ( JOIN_NB_RETRANSMISSION_DCYCLES == 0 )
-        return 0;
-
-    // Normalize system time values to seconds
-    uptime = TimerGetCurrentTime( ) / 1e6;
-    lastJoinTime = LastJoinTxTime / 1e6;
-
-    // Get dutycycle for current time
-    prevDCycleEndTime = 0;
-    currDCycleEndTime = 0;
-    for(dcyclePeriod = 0; dcyclePeriod < JOIN_NB_RETRANSMISSION_DCYCLES; dcyclePeriod++)
-    {                
-        prevDCycleEndTime  = currDCycleEndTime;
-        currDCycleEndTime += JoinReTransmitDCycle[dcyclePeriod].period;  
-
-        bool isCurrentPeriod = uptime < currDCycleEndTime;
-
-        if( isCurrentPeriod || ( dcyclePeriod == ( JOIN_NB_RETRANSMISSION_DCYCLES-1 ) ) )
-        {
-            period = JoinReTransmitDCycle[dcyclePeriod].period;
-            onAirTimeMax = JoinReTransmitDCycle[dcyclePeriod].onAirTimeMax;
-            if( isCurrentPeriod == true ) 
-                break;
-        }
-    }
-
-    // Clear aggregate on air time if dutycycle period of last join has elapsed 
-    if( lastJoinTime < prevDCycleEndTime ) 
-    {
-        JoinAggTimeOnAir = 0;
-    }
-    else 
-    {
-        elapsedTime = ( uptime - prevDCycleEndTime ) % period;
-        
-        if( dcyclePeriod == JOIN_NB_RETRANSMISSION_DCYCLES )
-        {
-            if( ( ( uptime - prevDCycleEndTime ) / period ) > ( ( lastJoinTime - prevDCycleEndTime ) / period ) )
-            {
-                JoinAggTimeOnAir = 0;
-            }
-        }
-    }
-
-    if ( JoinAggTimeOnAir >= onAirTimeMax ) 
-    {
-        // time off is remaining time until beginning of next period 
-        timeOff = ( period - elapsedTime ); 
-    }
-
-
-    if(timeOff > JOIN_RETRANSMISSION_DC_WAIT_MAX)
-    	timeOff = JOIN_RETRANSMISSION_DC_WAIT_MAX;
-
-    return ( timeOff * 1e6 );
-}
-
-void LoRaMacTestRxWindowsOn( bool enable )
-{
-    IsRxWindowsEnabled = enable;
-}
-
-void LoRaMacTestSetMic( uint16_t txPacketCounter )
-{
-    UpLinkCounter = txPacketCounter;
-    IsUpLinkCounterFixed = true;
-}
-
-void LoRaMacTestSetDutyCycleOn( bool enable )
-{
-    DutyCycleOn = enable;
-}