Fork of Semtech LoRaWAN stack
Fork of LoRaWAN-lib by
Revision 8:4816c8449bf2, committed 2016-08-22
- Comitter:
- snelson
- Date:
- Mon Aug 22 20:30:06 2016 -0400
- Branch:
- v4.2.0
- Parent:
- 6:d7a34ded7c87
- Child:
- 9:ad93de20d720
- Commit message:
- Merging Senet changes for:
- US915 Join Retransmission backoff
- US915 join channel selection
- Adr datarate decay
Changed in this revision
| LoRaMac.cpp | Show annotated file Show diff for this revision Revisions of this file |
| LoRaMac.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/LoRaMac.cpp Wed May 18 11:19:24 2016 +0000
+++ b/LoRaMac.cpp Mon Aug 22 20:30:06 2016 -0400
@@ -317,7 +317,7 @@
/*!
* Up/Down link data rates offset definition
*/
-const int8_t datarateOffsets[16][4] =
+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
@@ -369,6 +369,39 @@
* 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
+
#else
#error "Please define a frequency band in the compiler options."
#endif
@@ -560,6 +593,50 @@
*/
LoRaMacFlags_t LoRaMacFlags;
+/* LoRaWAN 1.1 Section 9 Retransmission back-off
+ *
+ * Applies to uplink frames that:
+ * - Require acknowledgement or answer, and are
+ * retransmitted by the device if the answer is not received
+ * and
+ * - Can be triggered by an external event causing synchronization
+ *
+ * Transmission duty-cylce for such messages shall respect the local regulations
+ * and the following limits
+ * - Aggregated during the first hour 36 seconds
+ * - Aggregated during the next 10 hours 36 seconds
+ * - After the first 11 hours aggregated over 24h 8.7seconds
+ */
+#ifndef JOIN_RETRANSMISSION_DCYCLE1
+#define JOIN_RETRANSMISSION_DCYCLE1 { 3600, 1000000 } // (period, onAirTimeMax)
+#endif
+
+#ifndef JOIN_RETRANSMISSION_DCYCLE2
+#define JOIN_RETRANSMISSION_DCYCLE2 { 10*3600, 36000000 } // (period, onAirTimeMax)
+#endif
+
+#ifndef JOIN_RETRANSMISSION_DCYCLE3
+#define JOIN_RETRANSMISSION_DCYCLE3 { 24*3600, 8700000 } // (period, onAirTimeMax)
+#endif
+
+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
*/
@@ -748,13 +825,15 @@
*
* \param [IN] adrEnabled Specify whether ADR is on or off
*
- * \param [IN] updateChannelMask Set to true, if the channel masks shall be updated
+ * \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 updateChannelMask, int8_t* datarateOut );
+static bool AdrNextDr( bool adrEnabled, bool isTx, int8_t* datarateOut, int8_t* txpowerOut );
/*!
* \brief Disables channel in a specified channel mask
@@ -842,6 +921,13 @@
// 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 );
@@ -1019,7 +1105,9 @@
#endif
MlmeConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
IsLoRaMacNetworkJoined = true;
- ChannelsDatarate = ChannelsDefaultDatarate;
+
+ // Do not change the datarate
+ // ChannelsDatarate = ChannelsDefaultDatarate;
}
else
{
@@ -1191,11 +1279,6 @@
}
}
- if( fCtrl.Bits.FOptsLen > 0 )
- {
- // Decode Options field MAC commands
- ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
- }
if( ( ( size - 4 ) - appPayloadStartIndex ) > 0 )
{
port = payload[appPayloadStartIndex++];
@@ -1205,19 +1288,32 @@
if( port == 0 )
{
- LoRaMacPayloadDecrypt( payload + appPayloadStartIndex,
- frameLen,
- nwkSKey,
- address,
- DOWN_LINK,
- downLinkCounter,
- LoRaMacRxPayload );
-
- // Decode frame payload MAC commands
- ProcessMacCommands( LoRaMacRxPayload, 0, frameLen, snr );
+ 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,
@@ -1234,6 +1330,15 @@
}
}
}
+ else
+ {
+ if( fCtrl.Bits.FOptsLen > 0 )
+ {
+ // Decode Options field MAC commands
+ ProcessMacCommands( payload, 8, appPayloadStartIndex, snr );
+ }
+ }
+
if( skipIndication == false )
{
LoRaMacFlags.Bits.McpsInd = 1;
@@ -1676,6 +1781,91 @@
}
}
+#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 == 0 ) || ( ( 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 )
+ {
+ channel = channel + ( curBlock * 8 );
+ JoinBlocksRemaining &= ~(1 << curBlock);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // 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 == 0 ) || ( ( Join500KHzRemaining & ( 1 << curChannel ) ) != 0 ) )
+ {
+ channel = 64 + curChannel;
+ Join500KHzRemaining &= ~(1 << channel);
+ 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;
@@ -1777,7 +1967,39 @@
if( nbEnabledChannels > 0 )
{
- Channel = enabledChannels[randr( 0, nbEnabledChannels - 1 )];
+#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 ) )
{
@@ -2028,82 +2250,75 @@
return true;
}
-static bool AdrNextDr( bool adrEnabled, bool updateChannelMask, int8_t* datarateOut )
+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 )
{
- if( datarate == LORAMAC_TX_MIN_DATARATE )
- {
- AdrAckCounter = 0;
- adrAckReq = false;
- }
- else
+ /* Request ADR Ack Request (including at lowest available datarate) */
+ adrAckReq = AdrAckCounter >= ADR_ACK_LIMIT ? true : false;
+
+ if( AdrAckCounter > (ADR_ACK_LIMIT + ADR_ACK_DELAY) )
{
- if( AdrAckCounter >= ADR_ACK_LIMIT )
- {
- adrAckReq = true;
- }
- else
- {
- adrAckReq = false;
- }
- if( AdrAckCounter >= ( ADR_ACK_LIMIT + ADR_ACK_DELAY ) )
- {
- if( ( ( AdrAckCounter - ADR_ACK_DELAY ) % ADR_ACK_LIMIT ) == 0 )
- {
+ // Step up power
+ txpower = LORAMAC_DEFAULT_TX_POWER;
+
+ // isTx=true when preparing to transmit the next frame
+ if(isTx == true)
+ AdrAckCounter = 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( updateChannelMask == true )
- {
-
- // Re-enable default channels LC1, LC2, LC3
- ChannelsMask[0] = ChannelsMask[0] | ( LC( 1 ) + LC( 2 ) + LC( 3 ) );
- }
- }
+ 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 ) && ( datarate == DR_8 ) )
- {
- datarate = DR_4;
- }
- else if( datarate > LORAMAC_TX_MIN_DATARATE )
- {
- datarate--;
- }
- if( datarate == LORAMAC_TX_MIN_DATARATE )
- {
- if( updateChannelMask == true )
- {
+ if( datarate > LORAMAC_TX_MIN_DATARATE )
+ {
+ 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;
+ // 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
- ReenableChannels( ChannelsMask[4], ChannelsMask );
+ // 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
- }
- }
}
}
- *datarateOut = datarate;
+ if(datarateOut != NULL)
+ *datarateOut = datarate;
+
+ if(txpowerOut != NULL)
+ *txpowerOut = txpower;
return adrAckReq;
}
@@ -2286,6 +2501,10 @@
}
}
}
+
+ // channel mask applied to 500 kHz channels
+ channelsMask[4] = chMask;
+ chMaskCntl = 4;
}
else if( chMaskCntl == 7 )
{
@@ -2294,13 +2513,18 @@
channelsMask[1] = 0x0000;
channelsMask[2] = 0x0000;
channelsMask[3] = 0x0000;
+
+ // channel mask applied to 500 kHz channels
+ channelsMask[4] = chMask;
+ chMaskCntl = 4;
}
else if( chMaskCntl == 5 )
{
// RFU
status &= 0xFE; // Channel mask KO
}
- else
+
+ if(status == 0xFF)
{
for( uint8_t i = 0; i < 16; i++ )
{
@@ -2660,7 +2884,7 @@
return LORAMAC_STATUS_NO_NETWORK_JOINED; // No network has been joined yet
}
- fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate );
+ fCtrl->Bits.AdrAckReq = AdrNextDr( fCtrl->Bits.Adr, true, &ChannelsDatarate, &ChannelsTxPower );
if( ValidatePayloadLength( fBufferSize, ChannelsDatarate, MacCommandsBufferIndex ) == false )
{
@@ -2850,6 +3074,31 @@
IsLoRaMacNetworkJoined = false;
LoRaMacState = MAC_IDLE;
+ MulticastChannels = NULL;
+ IsUpLinkCounterFixed = false;
+ IsRxWindowsEnabled = true;
+ IsLoRaMacNetworkJoined = false;
+ AdrCtrlOn = false;
+ AdrAckCounter = 0;
+ NodeAckRequested = false;
+ SrvAckRequested = false;
+ MacCommandsInNextTx = false;
+ MacCommandsBufferIndex = 0;
+ AckTimeoutRetries = 1;
+ AckTimeoutRetriesCounter = 1;
+ AckTimeoutRetry = false;
+ TxTimeOnAir = 0;
+ RxSlot = 0;
+ //Rx2Channel = RX_WND_2_CHANNEL;
+ Rx1DrOffset = 0;
+ ChannelsTxPower = LORAMAC_DEFAULT_TX_POWER;
+ ChannelsDatarate = LORAMAC_DEFAULT_DATARATE;
+ ChannelsDefaultDatarate = LORAMAC_DEFAULT_DATARATE;
+ ChannelsNbRep = 1;
+ ChannelsNbRepCounter = 0;
+ MaxDCycle = 0;
+
+
#if defined( USE_BAND_433 )
ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
#elif defined( USE_BAND_780 )
@@ -2923,6 +3172,16 @@
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 );
@@ -2961,7 +3220,7 @@
return LORAMAC_STATUS_PARAMETER_INVALID;
}
- AdrNextDr( AdrCtrlOn, false, &datarate );
+ AdrNextDr( AdrCtrlOn, false, &datarate, NULL );
if( RepeaterSupport == true )
{
@@ -3176,6 +3435,14 @@
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:
@@ -3628,10 +3895,23 @@
LoRaMacAppEui = mlmeRequest->Req.Join.AppEui;
LoRaMacAppKey = mlmeRequest->Req.Join.AppKey;
+ if( LoRaMacCalcJoinBackOff( ) != 0 )
+ {
+ return LORAMAC_STATUS_TX_DCYCLE_EXCEEDED;
+ }
+
macHdr.Value = 0;
macHdr.Bits.MType = FRAME_TYPE_JOIN_REQ;
- IsLoRaMacNetworkJoined = false;
+#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 )
@@ -3774,6 +4054,67 @@
return status;
}
+TimerTime_t LoRaMacCalcJoinBackOff( )
+{
+ TimerTime_t timeOff = 0;
+ TimerTime_t uptime;
+ TimerTime_t currDCycleEndTime;
+ TimerTime_t prevDCycleEndTime;
+ TimerTime_t period;
+ TimerTime_t onAirTimeMax;
+ uint8_t dcycleNum;
+
+ // Check retransmit duty-cycle exists
+ if ( JOIN_NB_RETRANSMISSION_DCYCLES == 0 )
+ return 0;
+
+ uptime = TimerGetCurrentTime( ) / 1e6;
+
+ // Get uptime dutycycle
+ prevDCycleEndTime = 0;
+ currDCycleEndTime = 0;
+ for(dcycleNum = 0; dcycleNum < JOIN_NB_RETRANSMISSION_DCYCLES; dcycleNum++)
+ {
+ prevDCycleEndTime = currDCycleEndTime;
+ currDCycleEndTime += JoinReTransmitDCycle[dcycleNum].period;
+
+ bool isCurrentPeriod = uptime < currDCycleEndTime;
+
+ if( isCurrentPeriod || ( dcycleNum == ( JOIN_NB_RETRANSMISSION_DCYCLES-1 ) ) )
+ {
+ period = JoinReTransmitDCycle[dcycleNum].period;
+ onAirTimeMax = JoinReTransmitDCycle[dcycleNum].onAirTimeMax;
+ if( isCurrentPeriod == true )
+ break;
+ }
+ }
+
+ // Clear aggregate on air time if last join occured during a previous period
+ if( LastJoinTxTime < prevDCycleEndTime )
+ {
+ JoinAggTimeOnAir = 0;
+ }
+ // For last dutycyle, the current & previous period end time must be calculated
+ else if( dcycleNum == JOIN_NB_RETRANSMISSION_DCYCLES )
+ {
+ if( ( TimerGetElapsedTime( LastJoinTxTime )/1e6 ) >= period )
+ {
+ JoinAggTimeOnAir = 0;
+ }
+ }
+
+ if ( JoinAggTimeOnAir >= onAirTimeMax )
+ {
+ // current period elapsed time
+ TimerTime_t elapsedTime = ( uptime - prevDCycleEndTime ) % period;
+
+ // time off is remaining time until beginning of next period
+ timeOff = ( period - elapsedTime ) * 1e6;
+ }
+
+ return timeOff;
+}
+
void LoRaMacTestRxWindowsOn( bool enable )
{
IsRxWindowsEnabled = enable;
--- a/LoRaMac.h Wed May 18 11:19:24 2016 +0000
+++ b/LoRaMac.h Mon Aug 22 20:30:06 2016 -0400
@@ -1,1707 +1,1748 @@
-/*!
- * \file LoRaMac.h
- *
- * \brief LoRa MAC layer implementation
- *
- * \copyright Revised BSD License, see section \ref LICENSE.
- *
- * \code
- * ______ _
- * / _____) _ | |
- * ( (____ _____ ____ _| |_ _____ ____| |__
- * \____ \| ___ | (_ _) ___ |/ ___) _ \
- * _____) ) ____| | | || |_| ____( (___| | | |
- * (______/|_____)_|_|_| \__)_____)\____)_| |_|
- * (C)2013 Semtech
- *
- * ___ _____ _ ___ _ _____ ___ ___ ___ ___
- * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
- * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
- * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
- * embedded.connectivity.solutions===============
- *
- * \endcode
- *
- * \author Miguel Luis ( Semtech )
- *
- * \author Gregory Cristian ( Semtech )
- *
- * \author Daniel Jäckle ( STACKFORCE )
- *
- * \defgroup LORAMAC LoRa MAC layer implementation
- * This module specifies the API implementation of the LoRaMAC layer.
- * This is a placeholder for a detailed description of the LoRaMac
- * layer and the supported features.
- * \{
- *
- * \example classA/LoRaMote/main.c
- * LoRaWAN class A application example for the LoRaMote.
- *
- * \example classB/LoRaMote/main.c
- * LoRaWAN class B application example for the LoRaMote.
- *
- * \example classC/LoRaMote/main.c
- * LoRaWAN class C application example for the LoRaMote.
- */
-#ifndef __LORAMAC_H__
-#define __LORAMAC_H__
-
-// Includes board dependent definitions such as channels frequencies
-#include "LoRaMac-board.h"
-
-/*!
- * Beacon interval in us
- */
-#define BEACON_INTERVAL 128000000
-
-/*!
- * Class A&B receive delay 1 in us
- */
-#define RECEIVE_DELAY1 1000000
-
-/*!
- * Class A&B receive delay 2 in us
- */
-#define RECEIVE_DELAY2 2000000
-
-/*!
- * Join accept receive delay 1 in us
- */
-#define JOIN_ACCEPT_DELAY1 5000000
-
-/*!
- * Join accept receive delay 2 in us
- */
-#define JOIN_ACCEPT_DELAY2 6000000
-
-/*!
- * Class A&B maximum receive window delay in us
- */
-#define MAX_RX_WINDOW 3000000
-
-/*!
- * Maximum allowed gap for the FCNT field
- */
-#define MAX_FCNT_GAP 16384
-
-/*!
- * ADR acknowledgement counter limit
- */
-#define ADR_ACK_LIMIT 64
-
-/*!
- * Number of ADR acknowledgement requests before returning to default datarate
- */
-#define ADR_ACK_DELAY 32
-
-/*!
- * Number of seconds after the start of the second reception window without
- * receiving an acknowledge.
- * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
- */
-#define ACK_TIMEOUT 2000000
-
-/*!
- * Random number of seconds after the start of the second reception window without
- * receiving an acknowledge
- * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
- */
-#define ACK_TIMEOUT_RND 1000000
-
-/*!
- * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in us
- */
-#define MAC_STATE_CHECK_TIMEOUT 1000000
-
-/*!
- * Maximum number of times the MAC layer tries to get an acknowledge.
- */
-#define MAX_ACK_RETRIES 8
-
-/*!
- * RSSI free threshold [dBm]
- */
-#define RSSI_FREE_TH ( int8_t )( -90 )
-
-/*!
- * Frame direction definition for up-link communications
- */
-#define UP_LINK 0
-
-/*!
- * Frame direction definition for down-link communications
- */
-#define DOWN_LINK 1
-
-/*!
- * Sets the length of the LoRaMAC footer field.
- * Mainly indicates the MIC field length
- */
-#define LORAMAC_MFR_LEN 4
-
-/*!
- * Syncword for Private LoRa networks
- */
-#define LORA_MAC_PRIVATE_SYNCWORD 0x12
-
-/*!
- * Syncword for Public LoRa networks
- */
-#define LORA_MAC_PUBLIC_SYNCWORD 0x34
-
- /*!
- * LoRaMac internal state
- */
-//uint32_t LoRaMacState;
-
-/*!
- * LoRaWAN devices classes definition
- */
-typedef enum eDeviceClass
-{
- /*!
- * LoRaWAN device class A
- *
- * LoRaWAN Specification V1.0, chapter 3ff
- */
- CLASS_A,
- /*!
- * LoRaWAN device class B
- *
- * LoRaWAN Specification V1.0, chapter 8ff
- */
- CLASS_B,
- /*!
- * LoRaWAN device class C
- *
- * LoRaWAN Specification V1.0, chapter 17ff
- */
- CLASS_C,
-}DeviceClass_t;
-
-/*!
- * LoRaMAC channels parameters definition
- */
-typedef union uDrRange
-{
- /*!
- * Byte-access to the bits
- */
- int8_t Value;
- /*!
- * Structure to store the minimum and the maximum datarate
- */
- struct sFields
- {
- /*!
- * Minimum data rate
- *
- * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
- *
- * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4]
- */
- int8_t Min : 4;
- /*!
- * Maximum data rate
- *
- * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
- *
- * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4]
- */
- int8_t Max : 4;
- }Fields;
-}DrRange_t;
-
-/*!
- * LoRaMAC band parameters definition
- */
-typedef struct sBand
-{
- /*!
- * Duty cycle
- */
- uint16_t DCycle;
- /*!
- * Maximum Tx power
- */
- int8_t TxMaxPower;
- /*!
- * Time stamp of the last Tx frame
- */
- TimerTime_t LastTxDoneTime;
- /*!
- * Holds the time where the device is off
- */
- TimerTime_t TimeOff;
-}Band_t;
-
-/*!
- * LoRaMAC channel definition
- */
-typedef struct sChannelParams
-{
- /*!
- * Frequency in Hz
- */
- uint32_t Frequency;
- /*!
- * Data rate definition
- */
- DrRange_t DrRange;
- /*!
- * Band index
- */
- uint8_t Band;
-}ChannelParams_t;
-
-/*!
- * LoRaMAC receive window 2 channel parameters
- */
-typedef struct sRx2ChannelParams
-{
- /*!
- * Frequency in Hz
- */
- uint32_t Frequency;
- /*!
- * Data rate
- *
- * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
- *
- * US915 - [DR_8, DR_9, DR_10, DR_11, DR_12, DR_13]
- */
- uint8_t Datarate;
-}Rx2ChannelParams_t;
-
-/*!
- * LoRaMAC multicast channel parameter
- */
-typedef struct sMulticastParams
-{
- /*!
- * Address
- */
- uint32_t Address;
- /*!
- * Network session key
- */
- uint8_t NwkSKey[16];
- /*!
- * Application session key
- */
- uint8_t AppSKey[16];
- /*!
- * Downlink counter
- */
- uint32_t DownLinkCounter;
- /*!
- * Reference pointer to the next multicast channel parameters in the list
- */
- struct sMulticastParams *Next;
-}MulticastParams_t;
-
-/*!
- * LoRaMAC frame types
- *
- * LoRaWAN Specification V1.0, chapter 4.2.1, table 1
- */
-typedef enum eLoRaMacFrameType
-{
- /*!
- * LoRaMAC join request frame
- */
- FRAME_TYPE_JOIN_REQ = 0x00,
- /*!
- * LoRaMAC join accept frame
- */
- FRAME_TYPE_JOIN_ACCEPT = 0x01,
- /*!
- * LoRaMAC unconfirmed up-link frame
- */
- FRAME_TYPE_DATA_UNCONFIRMED_UP = 0x02,
- /*!
- * LoRaMAC unconfirmed down-link frame
- */
- FRAME_TYPE_DATA_UNCONFIRMED_DOWN = 0x03,
- /*!
- * LoRaMAC confirmed up-link frame
- */
- FRAME_TYPE_DATA_CONFIRMED_UP = 0x04,
- /*!
- * LoRaMAC confirmed down-link frame
- */
- FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05,
- /*!
- * LoRaMAC RFU frame
- */
- FRAME_TYPE_RFU = 0x06,
- /*!
- * LoRaMAC proprietary frame
- */
- FRAME_TYPE_PROPRIETARY = 0x07,
-}LoRaMacFrameType_t;
-
-/*!
- * LoRaMAC mote MAC commands
- *
- * LoRaWAN Specification V1.0, chapter 5, table 4
- */
-typedef enum eLoRaMacMoteCmd
-{
- /*!
- * LinkCheckReq
- */
- MOTE_MAC_LINK_CHECK_REQ = 0x02,
- /*!
- * LinkADRAns
- */
- MOTE_MAC_LINK_ADR_ANS = 0x03,
- /*!
- * DutyCycleAns
- */
- MOTE_MAC_DUTY_CYCLE_ANS = 0x04,
- /*!
- * RXParamSetupAns
- */
- MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05,
- /*!
- * DevStatusAns
- */
- MOTE_MAC_DEV_STATUS_ANS = 0x06,
- /*!
- * NewChannelAns
- */
- MOTE_MAC_NEW_CHANNEL_ANS = 0x07,
- /*!
- * RXTimingSetupAns
- */
- MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08,
-}LoRaMacMoteCmd_t;
-
-/*!
- * LoRaMAC server MAC commands
- *
- * LoRaWAN Specification V1.0, chapter 5, table 4
- */
-typedef enum eLoRaMacSrvCmd
-{
- /*!
- * LinkCheckAns
- */
- SRV_MAC_LINK_CHECK_ANS = 0x02,
- /*!
- * LinkADRReq
- */
- SRV_MAC_LINK_ADR_REQ = 0x03,
- /*!
- * DutyCycleReq
- */
- SRV_MAC_DUTY_CYCLE_REQ = 0x04,
- /*!
- * RXParamSetupReq
- */
- SRV_MAC_RX_PARAM_SETUP_REQ = 0x05,
- /*!
- * DevStatusReq
- */
- SRV_MAC_DEV_STATUS_REQ = 0x06,
- /*!
- * NewChannelReq
- */
- SRV_MAC_NEW_CHANNEL_REQ = 0x07,
- /*!
- * RXTimingSetupReq
- */
- SRV_MAC_RX_TIMING_SETUP_REQ = 0x08,
-}LoRaMacSrvCmd_t;
-
-/*!
- * LoRaMAC Battery level indicator
- */
-typedef enum eLoRaMacBatteryLevel
-{
- /*!
- * External power source
- */
- BAT_LEVEL_EXT_SRC = 0x00,
- /*!
- * Battery level empty
- */
- BAT_LEVEL_EMPTY = 0x01,
- /*!
- * Battery level full
- */
- BAT_LEVEL_FULL = 0xFE,
- /*!
- * Battery level - no measurement available
- */
- BAT_LEVEL_NO_MEASURE = 0xFF,
-}LoRaMacBatteryLevel_t;
-
-/*!
- * LoRaMAC header field definition (MHDR field)
- *
- * LoRaWAN Specification V1.0, chapter 4.2
- */
-typedef union uLoRaMacHeader
-{
- /*!
- * Byte-access to the bits
- */
- uint8_t Value;
- /*!
- * Structure containing single access to header bits
- */
- struct sHdrBits
- {
- /*!
- * Major version
- */
- uint8_t Major : 2;
- /*!
- * RFU
- */
- uint8_t RFU : 3;
- /*!
- * Message type
- */
- uint8_t MType : 3;
- }Bits;
-}LoRaMacHeader_t;
-
-/*!
- * LoRaMAC frame control field definition (FCtrl)
- *
- * LoRaWAN Specification V1.0, chapter 4.3.1
- */
-typedef union uLoRaMacFrameCtrl
-{
- /*!
- * Byte-access to the bits
- */
- uint8_t Value;
- /*!
- * Structure containing single access to bits
- */
- struct sCtrlBits
- {
- /*!
- * Frame options length
- */
- uint8_t FOptsLen : 4;
- /*!
- * Frame pending bit
- */
- uint8_t FPending : 1;
- /*!
- * Message acknowledge bit
- */
- uint8_t Ack : 1;
- /*!
- * ADR acknowledgment request bit
- */
- uint8_t AdrAckReq : 1;
- /*!
- * ADR control in frame header
- */
- uint8_t Adr : 1;
- }Bits;
-}LoRaMacFrameCtrl_t;
-
-/*!
- * Enumeration containing the status of the operation of a MAC service
- */
-typedef enum eLoRaMacEventInfoStatus
-{
- /*!
- * Service performed successfully
- */
- LORAMAC_EVENT_INFO_STATUS_OK = 0,
- /*!
- * An error occured during the execution of the service
- */
- LORAMAC_EVENT_INFO_STATUS_ERROR,
- /*!
- * A Tx timeouit occured
- */
- LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT,
- /*!
- * An Rx timeout occured on receive window 2
- */
- LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT,
- /*!
- * An Rx error occured on receive window 2
- */
- LORAMAC_EVENT_INFO_STATUS_RX2_ERROR,
- /*!
- * An error occured in the join procedure
- */
- LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL,
- /*!
- * A frame with an invalid downlink counter was received. The
- * downlink counter of the frame was equal to the local copy
- * of the downlink counter of the node.
- */
- LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED,
- /*!
- * The node has lost MAX_FCNT_GAP or more frames.
- */
- LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS,
- /*!
- * An address error occured
- */
- LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL,
- /*!
- * message integrity check failure
- */
- LORAMAC_EVENT_INFO_STATUS_MIC_FAIL,
-}LoRaMacEventInfoStatus_t;
-
-/*!
- * LoRaMac tx/rx operation state
- */
-typedef union eLoRaMacFlags_t
-{
- /*!
- * Byte-access to the bits
- */
- uint8_t Value;
- /*!
- * Structure containing single access to bits
- */
- struct sMacFlagBits
- {
- /*!
- * MCPS-Req pending
- */
- uint8_t McpsReq : 1;
- /*!
- * MCPS-Ind pending
- */
- uint8_t McpsInd : 1;
- /*!
- * MLME-Req pending
- */
- uint8_t MlmeReq : 1;
- /*!
- * MAC cycle done
- */
- uint8_t MacDone : 1;
- }Bits;
-}LoRaMacFlags_t;
-
-/*!
- *
- * \brief LoRaMAC data services
- *
- * \details The following table list the primitives which are supported by the
- * specific MAC data service:
- *
- * Name | Request | Indication | Response | Confirm
- * --------------------- | :-----: | :--------: | :------: | :-----:
- * \ref MCPS_UNCONFIRMED | YES | YES | NO | YES
- * \ref MCPS_CONFIRMED | YES | YES | NO | YES
- * \ref MCPS_MULTICAST | NO | YES | NO | NO
- * \ref MCPS_PROPRIETARY | YES | YES | NO | YES
- *
- * The following table provides links to the function implementations of the
- * related MCPS primitives:
- *
- * Primitive | Function
- * ---------------- | :---------------------:
- * MCPS-Request | \ref LoRaMacMlmeRequest
- * MCPS-Confirm | MacMcpsConfirm in \ref LoRaMacPrimitives_t
- * MCPS-Indication | MacMcpsIndication in \ref LoRaMacPrimitives_t
- */
-typedef enum eMcps
-{
- /*!
- * Unconfirmed LoRaMAC frame
- */
- MCPS_UNCONFIRMED,
- /*!
- * Confirmed LoRaMAC frame
- */
- MCPS_CONFIRMED,
- /*!
- * Multicast LoRaMAC frame
- */
- MCPS_MULTICAST,
- /*!
- * Proprietary frame
- */
- MCPS_PROPRIETARY,
-}Mcps_t;
-
-/*!
- * LoRaMAC MCPS-Request for an unconfirmed frame
- */
-typedef struct sMcpsReqUnconfirmed
-{
- /*!
- * Frame port field. Must be set if the payload is not empty. Use the
- * application specific frame port values: [1...223]
- *
- * LoRaWAN Specification V1.0, chapter 4.3.2
- */
- uint8_t fPort;
- /*!
- * Pointer to the buffer of the frame payload
- */
- void *fBuffer;
- /*!
- * Size of the frame payload
- */
- uint16_t fBufferSize;
- /*!
- * Uplink datarate, if ADR is off
- */
- int8_t Datarate;
-}McpsReqUnconfirmed_t;
-
-/*!
- * LoRaMAC MCPS-Request for a confirmed frame
- */
-typedef struct sMcpsReqConfirmed
-{
- /*!
- * Frame port field. Must be set if the payload is not empty. Use the
- * application specific frame port values: [1...223]
- *
- * LoRaWAN Specification V1.0, chapter 4.3.2
- */
- uint8_t fPort;
- /*!
- * Pointer to the buffer of the frame payload
- */
- void *fBuffer;
- /*!
- * Size of the frame payload
- */
- uint16_t fBufferSize;
- /*!
- * Uplink datarate, if ADR is off
- */
- int8_t Datarate;
- /*!
- * Number of trials to transmit the frame, if the LoRaMAC layer did not
- * receive an acknowledgment. The MAC performs a datarate adaptation,
- * according to the LoRaWAN Specification V1.0, chapter 18.4, according
- * to the following table:
- *
- * Transmission nb | Data Rate
- * ----------------|-----------
- * 1 (first) | DR
- * 2 | DR
- * 3 | max(DR-1,0)
- * 4 | max(DR-1,0)
- * 5 | max(DR-2,0)
- * 6 | max(DR-2,0)
- * 7 | max(DR-3,0)
- * 8 | max(DR-3,0)
- *
- * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease
- * the datarate, in case the LoRaMAC layer did not receive an acknowledgment
- */
- uint8_t NbTrials;
-}McpsReqConfirmed_t;
-
-/*!
- * LoRaMAC MCPS-Request for a proprietary frame
- */
-typedef struct sMcpsReqProprietary
-{
- /*!
- * Pointer to the buffer of the frame payload
- */
- void *fBuffer;
- /*!
- * Size of the frame payload
- */
- uint16_t fBufferSize;
- /*!
- * Uplink datarate, if ADR is off
- */
- int8_t Datarate;
-}McpsReqProprietary_t;
-
-/*!
- * LoRaMAC MCPS-Request structure
- */
-typedef struct sMcpsReq
-{
- /*!
- * MCPS-Request type
- */
- Mcps_t Type;
-
- /*!
- * MCPS-Request parameters
- */
- union uMcpsParam
- {
- /*!
- * MCPS-Request parameters for an unconfirmed frame
- */
- McpsReqUnconfirmed_t Unconfirmed;
- /*!
- * MCPS-Request parameters for a confirmed frame
- */
- McpsReqConfirmed_t Confirmed;
- /*!
- * MCPS-Request parameters for a proprietary frame
- */
- McpsReqProprietary_t Proprietary;
- }Req;
-}McpsReq_t;
-
-/*!
- * LoRaMAC MCPS-Confirm
- */
-typedef struct sMcpsConfirm
-{
- /*!
- * Holds the previously performed MCPS-Request
- */
- Mcps_t McpsRequest;
- /*!
- * Status of the operation
- */
- LoRaMacEventInfoStatus_t Status;
- /*!
- * Uplink datarate
- */
- uint8_t Datarate;
- /*!
- * Transmission power
- */
- int8_t TxPower;
- /*!
- * Set if an acknowledgement was received
- */
- bool AckReceived;
- /*!
- * Provides the number of retransmissions
- */
- uint8_t NbRetries;
- /*!
- * The transmission time on air of the frame
- */
- TimerTime_t TxTimeOnAir;
- /*!
- * The uplink counter value related to the frame
- */
- uint32_t UpLinkCounter;
-}McpsConfirm_t;
-
-/*!
- * LoRaMAC MCPS-Indication primitive
- */
-typedef struct sMcpsIndication
-{
- /*!
- * MCPS-Indication type
- */
- Mcps_t McpsIndication;
- /*!
- * Status of the operation
- */
- LoRaMacEventInfoStatus_t Status;
- /*!
- * Multicast
- */
- uint8_t Multicast;
- /*!
- * Application port
- */
- uint8_t Port;
- /*!
- * Downlink datarate
- */
- uint8_t RxDatarate;
- /*!
- * Frame pending status
- */
- uint8_t FramePending;
- /*!
- * Pointer to the received data stream
- */
- uint8_t *Buffer;
- /*!
- * Size of the received data stream
- */
- uint8_t BufferSize;
- /*!
- * Indicates, if data is available
- */
- bool RxData;
- /*!
- * Rssi of the received packet
- */
- int16_t Rssi;
- /*!
- * Snr of the received packet
- */
- uint8_t Snr;
- /*!
- * Receive window
- *
- * [0: Rx window 1, 1: Rx window 2]
- */
- uint8_t RxSlot;
- /*!
- * Set if an acknowledgement was received
- */
- bool AckReceived;
- /*!
- * The downlink counter value for the received frame
- */
- uint32_t DownLinkCounter;
-}McpsIndication_t;
-
-/*!
- * \brief LoRaMAC management services
- *
- * \details The following table list the primitives which are supported by the
- * specific MAC management service:
- *
- * Name | Request | Indication | Response | Confirm
- * --------------------- | :-----: | :--------: | :------: | :-----:
- * \ref MLME_JOIN | YES | NO | NO | YES
- * \ref MLME_LINK_CHECK | YES | NO | NO | YES
- *
- * The following table provides links to the function implementations of the
- * related MLME primitives.
- *
- * Primitive | Function
- * ---------------- | :---------------------:
- * MLME-Request | \ref LoRaMacMlmeRequest
- * MLME-Confirm | MacMlmeConfirm in \ref LoRaMacPrimitives_t
- */
-typedef enum eMlme
-{
- /*!
- * Initiates the Over-the-Air activation
- *
- * LoRaWAN Specification V1.0, chapter 6.2
- */
- MLME_JOIN,
- /*!
- * LinkCheckReq - Connectivity validation
- *
- * LoRaWAN Specification V1.0, chapter 5, table 4
- */
- MLME_LINK_CHECK,
-}Mlme_t;
-
-/*!
- * LoRaMAC MLME-Request for the join service
- */
-typedef struct sMlmeReqJoin
-{
- /*!
- * Globally unique end-device identifier
- *
- * LoRaWAN Specification V1.0, chapter 6.2.1
- */
- uint8_t *DevEui;
- /*!
- * Application identifier
- *
- * LoRaWAN Specification V1.0, chapter 6.1.2
- */
- uint8_t *AppEui;
- /*!
- * AES-128 application key
- *
- * LoRaWAN Specification V1.0, chapter 6.2.2
- */
- uint8_t *AppKey;
-}MlmeReqJoin_t;
-
-/*!
- * LoRaMAC MLME-Request structure
- */
-typedef struct sMlmeReq
-{
- /*!
- * MLME-Request type
- */
- Mlme_t Type;
-
- /*!
- * MLME-Request parameters
- */
- union uMlmeParam
- {
- /*!
- * MLME-Request parameters for a join request
- */
- MlmeReqJoin_t Join;
- }Req;
-}MlmeReq_t;
-
-/*!
- * LoRaMAC MLME-Confirm primitive
- */
-typedef struct sMlmeConfirm
-{
- /*!
- * Holds the previously performed MLME-Request
- */
- Mlme_t MlmeRequest;
- /*!
- * Status of the operation
- */
- LoRaMacEventInfoStatus_t Status;
- /*!
- * The transmission time on air of the frame
- */
- TimerTime_t TxTimeOnAir;
- /*!
- * Demodulation margin. Contains the link margin [dB] of the last
- * successfully received LinkCheckReq
- */
- uint8_t DemodMargin;
- /*!
- * Number of gateways which received the last LinkCheckReq
- */
- uint8_t NbGateways;
-}MlmeConfirm_t;
-
-/*!
- * LoRa Mac Information Base (MIB)
- *
- * The following table lists the MIB parameters and the related attributes:
- *
- * Attribute | Get | Set
- * --------------------------------- | :-: | :-:
- * \ref MIB_DEVICE_CLASS | YES | YES
- * \ref MIB_NETWORK_JOINED | YES | YES
- * \ref MIB_ADR | YES | YES
- * \ref MIB_NET_ID | YES | YES
- * \ref MIB_DEV_ADDR | YES | YES
- * \ref MIB_NWK_SKEY | YES | YES
- * \ref MIB_APP_SKEY | YES | YES
- * \ref MIB_PUBLIC_NETWORK | YES | YES
- * \ref MIB_REPEATER_SUPPORT | YES | YES
- * \ref MIB_CHANNELS | YES | NO
- * \ref MIB_RX2_CHANNEL | YES | YES
- * \ref MIB_CHANNELS_MASK | YES | YES
- * \ref MIB_CHANNELS_NB_REP | YES | YES
- * \ref MIB_MAX_RX_WINDOW_DURATION | YES | YES
- * \ref MIB_RECEIVE_DELAY_1 | YES | YES
- * \ref MIB_RECEIVE_DELAY_2 | YES | YES
- * \ref MIB_JOIN_ACCEPT_DELAY_1 | YES | YES
- * \ref MIB_JOIN_ACCEPT_DELAY_2 | YES | YES
- * \ref MIB_CHANNELS_DATARATE | YES | YES
- * \ref MIB_CHANNELS_DEFAULT_DATARATE| YES | YES
- * \ref MIB_CHANNELS_TX_POWER | YES | YES
- * \ref MIB_UPLINK_COUNTER | YES | YES
- * \ref MIB_DOWNLINK_COUNTER | YES | YES
- * \ref MIB_MULTICAST_CHANNEL | YES | NO
- *
- * The following table provides links to the function implementations of the
- * related MIB primitives:
- *
- * Primitive | Function
- * ---------------- | :---------------------:
- * MIB-Set | \ref LoRaMacMibSetRequestConfirm
- * MIB-Get | \ref LoRaMacMibGetRequestConfirm
- */
-typedef enum eMib
-{
- /*!
- * LoRaWAN device class
- *
- * LoRaWAN Specification V1.0
- */
- MIB_DEVICE_CLASS,
- /*!
- * LoRaWAN Network joined attribute
- *
- * LoRaWAN Specification V1.0
- */
- MIB_NETWORK_JOINED,
- /*!
- * Adaptive data rate
- *
- * LoRaWAN Specification V1.0, chapter 4.3.1.1
- *
- * [true: ADR enabled, false: ADR disabled]
- */
- MIB_ADR,
- /*!
- * Network identifier
- *
- * LoRaWAN Specification V1.0, chapter 6.2.5
- */
- MIB_NET_ID,
- /*!
- * End-device address
- *
- * LoRaWAN Specification V1.0, chapter 6.1.2
- */
- MIB_DEV_ADDR,
- /*!
- * Network session key
- *
- * LoRaWAN Specification V1.0, chapter 6.1.3
- */
- MIB_NWK_SKEY,
- /*!
- * Application session key
- *
- * LoRaWAN Specification V1.0, chapter 6.1.4
- */
- MIB_APP_SKEY,
- /*!
- * Set the network type to public or private
- *
- * LoRaWAN Specification V1.0, chapter 7
- *
- * [true: public network, false: private network]
- */
- MIB_PUBLIC_NETWORK,
- /*!
- * Support the operation with repeaters
- *
- * LoRaWAN Specification V1.0, chapter 7
- *
- * [true: repeater support enabled, false: repeater support disabled]
- */
- MIB_REPEATER_SUPPORT,
- /*!
- * Communication channels. A get request will return a
- * pointer which references the first entry of the channel list. The
- * list is of size LORA_MAX_NB_CHANNELS
- *
- * LoRaWAN Specification V1.0, chapter 7
- */
- MIB_CHANNELS,
- /*!
- * Set receive window 2 channel
- *
- * LoRaWAN Specification V1.0, chapter 3.3.2
- */
- MIB_RX2_CHANNEL,
- /*!
- * LoRaWAN channels mask
- *
- * LoRaWAN Specification V1.0, chapter 5.2
- */
- MIB_CHANNELS_MASK,
- /*!
- * Set the number of repetitions on a channel
- *
- * LoRaWAN Specification V1.0, chapter 5.2
- */
- MIB_CHANNELS_NB_REP,
- /*!
- * Maximum receive window duration in [us]
- *
- * LoRaWAN Specification V1.0, chapter 3.3.3
- */
- MIB_MAX_RX_WINDOW_DURATION,
- /*!
- * Receive delay 1 in [us]
- *
- * LoRaWAN Specification V1.0, chapter 6
- */
- MIB_RECEIVE_DELAY_1,
- /*!
- * Receive delay 2 in [us]
- *
- * LoRaWAN Specification V1.0, chapter 6
- */
- MIB_RECEIVE_DELAY_2,
- /*!
- * Join accept delay 1 in [us]
- *
- * LoRaWAN Specification V1.0, chapter 6
- */
- MIB_JOIN_ACCEPT_DELAY_1,
- /*!
- * Join accept delay 2 in [us]
- *
- * LoRaWAN Specification V1.0, chapter 6
- */
- MIB_JOIN_ACCEPT_DELAY_2,
- /*!
- * Default Data rate of a channel
- *
- * LoRaWAN Specification V1.0, chapter 7
- *
- * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
- *
- * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13]
- */
- MIB_CHANNELS_DEFAULT_DATARATE,
- /*!
- * Data rate of a channel
- *
- * LoRaWAN Specification V1.0, chapter 7
- *
- * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
- *
- * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13]
- */
- MIB_CHANNELS_DATARATE,
- /*!
- * Transmission power of a channel
- *
- * LoRaWAN Specification V1.0, chapter 7
- *
- * EU868 - [TX_POWER_20_DBM, TX_POWER_14_DBM, TX_POWER_11_DBM,
- * TX_POWER_08_DBM, TX_POWER_05_DBM, TX_POWER_02_DBM]
- *
- * US915 - [TX_POWER_30_DBM, TX_POWER_28_DBM, TX_POWER_26_DBM,
- * TX_POWER_24_DBM, TX_POWER_22_DBM, TX_POWER_20_DBM,
- * TX_POWER_18_DBM, TX_POWER_14_DBM, TX_POWER_12_DBM,
- * TX_POWER_10_DBM]
- */
- MIB_CHANNELS_TX_POWER,
- /*!
- * LoRaWAN Up-link counter
- *
- * LoRaWAN Specification V1.0, chapter 4.3.1.5
- */
- MIB_UPLINK_COUNTER,
- /*!
- * LoRaWAN Down-link counter
- *
- * LoRaWAN Specification V1.0, chapter 4.3.1.5
- */
- MIB_DOWNLINK_COUNTER,
- /*!
- * Multicast channels. A get request will return a pointer to the first
- * entry of the multicast channel linked list. If the pointer is equal to
- * NULL, the list is empty.
- */
- MIB_MULTICAST_CHANNEL,
-}Mib_t;
-
-/*!
- * LoRaMAC MIB parameters
- */
-typedef union uMibParam
-{
- /*!
- * LoRaWAN device class
- *
- * Related MIB type: \ref MIB_DEVICE_CLASS
- */
- DeviceClass_t Class;
- /*!
- * LoRaWAN network joined attribute
- *
- * Related MIB type: \ref MIB_NETWORK_JOINED
- */
- bool IsNetworkJoined;
- /*!
- * Activation state of ADR
- *
- * Related MIB type: \ref MIB_ADR
- */
- bool AdrEnable;
- /*!
- * Network identifier
- *
- * Related MIB type: \ref MIB_NET_ID
- */
- uint32_t NetID;
- /*!
- * End-device address
- *
- * Related MIB type: \ref MIB_DEV_ADDR
- */
- uint32_t DevAddr;
- /*!
- * Network session key
- *
- * Related MIB type: \ref MIB_NWK_SKEY
- */
- uint8_t *NwkSKey;
- /*!
- * Application session key
- *
- * Related MIB type: \ref MIB_APP_SKEY
- */
- uint8_t *AppSKey;
- /*!
- * Enable or disable a public network
- *
- * Related MIB type: \ref MIB_PUBLIC_NETWORK
- */
- bool EnablePublicNetwork;
- /*!
- * Enable or disable repeater support
- *
- * Related MIB type: \ref MIB_REPEATER_SUPPORT
- */
- bool EnableRepeaterSupport;
- /*!
- * LoRaWAN Channel
- *
- * Related MIB type: \ref MIB_CHANNELS
- */
- ChannelParams_t* ChannelList;
- /*!
- * Channel for the receive window 2
- *
- * Related MIB type: \ref MIB_RX2_CHANNEL
- */
- Rx2ChannelParams_t Rx2Channel;
- /*!
- * Channel mask
- *
- * Related MIB type: \ref MIB_CHANNELS_MASK
- */
- uint16_t* ChannelsMask;
- /*!
- * Number of frame repetitions
- *
- * Related MIB type: \ref MIB_CHANNELS_NB_REP
- */
- uint8_t ChannelNbRep;
- /*!
- * Maximum receive window duration
- *
- * Related MIB type: \ref MIB_MAX_RX_WINDOW_DURATION
- */
- uint32_t MaxRxWindow;
- /*!
- * Receive delay 1
- *
- * Related MIB type: \ref MIB_RECEIVE_DELAY_1
- */
- uint32_t ReceiveDelay1;
- /*!
- * Receive delay 2
- *
- * Related MIB type: \ref MIB_RECEIVE_DELAY_2
- */
- uint32_t ReceiveDelay2;
- /*!
- * Join accept delay 1
- *
- * Related MIB type: \ref MIB_JOIN_ACCEPT_DELAY_1
- */
- uint32_t JoinAcceptDelay1;
- /*!
- * Join accept delay 2
- *
- * Related MIB type: \ref MIB_JOIN_ACCEPT_DELAY_2
- */
- uint32_t JoinAcceptDelay2;
- /*!
- * Channels data rate
- *
- * Related MIB type: \ref MIB_CHANNELS_DEFAULT_DATARATE
- */
- int8_t ChannelsDefaultDatarate;
- /*!
- * Channels data rate
- *
- * Related MIB type: \ref MIB_CHANNELS_DATARATE
- */
- int8_t ChannelsDatarate;
- /*!
- * Channels TX power
- *
- * Related MIB type: \ref MIB_CHANNELS_TX_POWER
- */
- int8_t ChannelsTxPower;
- /*!
- * LoRaWAN Up-link counter
- *
- * Related MIB type: \ref MIB_UPLINK_COUNTER
- */
- uint32_t UpLinkCounter;
- /*!
- * LoRaWAN Down-link counter
- *
- * Related MIB type: \ref MIB_DOWNLINK_COUNTER
- */
- uint32_t DownLinkCounter;
- /*!
- * Multicast channel
- *
- * Related MIB type: \ref MIB_MULTICAST_CHANNEL
- */
- MulticastParams_t* MulticastList;
-}MibParam_t;
-
-/*!
- * LoRaMAC MIB-RequestConfirm structure
- */
-typedef struct eMibRequestConfirm
-{
- /*!
- * MIB-Request type
- */
- Mib_t Type;
-
- /*!
- * MLME-RequestConfirm parameters
- */
- MibParam_t Param;
-}MibRequestConfirm_t;
-
-/*!
- * LoRaMAC tx information
- */
-typedef struct sLoRaMacTxInfo
-{
- /*!
- * Defines the size of the applicative payload which can be processed
- */
- uint8_t MaxPossiblePayload;
- /*!
- * The current payload size, dependent on the current datarate
- */
- uint8_t CurrentPayloadSize;
-}LoRaMacTxInfo_t;
-
-/*!
- * LoRaMAC Status
- */
-typedef enum eLoRaMacStatus
-{
- /*!
- * Service started successfully
- */
- LORAMAC_STATUS_OK,
- /*!
- * Service not started - LoRaMAC is busy
- */
- LORAMAC_STATUS_BUSY,
- /*!
- * Service unknown
- */
- LORAMAC_STATUS_SERVICE_UNKNOWN,
- /*!
- * Service not started - invalid parameter
- */
- LORAMAC_STATUS_PARAMETER_INVALID,
- /*!
- * Service not started - invalid frequency
- */
- LORAMAC_STATUS_FREQUENCY_INVALID,
- /*!
- * Service not started - invalid datarate
- */
- LORAMAC_STATUS_DATARATE_INVALID,
- /*!
- * Service not started - invalid frequency and datarate
- */
- LORAMAC_STATUS_FREQ_AND_DR_INVALID,
- /*!
- * Service not started - the device is not in a LoRaWAN
- */
- LORAMAC_STATUS_NO_NETWORK_JOINED,
- /*!
- * Service not started - playload lenght error
- */
- LORAMAC_STATUS_LENGTH_ERROR,
- /*!
- * Service not started - playload lenght error
- */
- LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR,
- /*!
- * Service not started - the device is switched off
- */
- LORAMAC_STATUS_DEVICE_OFF,
-}LoRaMacStatus_t;
-
-/*!
- * LoRaMAC events structure
- * Used to notify upper layers of MAC events
- */
-typedef struct sLoRaMacPrimitives
-{
- /*!
- * \brief MCPS-Confirm primitive
- *
- * \param [OUT] MCPS-Confirm parameters
- */
- void ( *MacMcpsConfirm )( McpsConfirm_t *McpsConfirm );
- /*!
- * \brief MCPS-Indication primitive
- *
- * \param [OUT] MCPS-Indication parameters
- */
- void ( *MacMcpsIndication )( McpsIndication_t *McpsIndication );
- /*!
- * \brief MLME-Confirm primitive
- *
- * \param [OUT] MLME-Confirm parameters
- */
- void ( *MacMlmeConfirm )( MlmeConfirm_t *MlmeConfirm );
-}LoRaMacPrimitives_t;
-
-typedef struct sLoRaMacCallback
-{
- /*!
- * \brief Measures the battery level
- *
- * \retval Battery level [0: node is connected to an external
- * power source, 1..254: battery level, where 1 is the minimum
- * and 254 is the maximum value, 255: the node was not able
- * to measure the battery level]
- */
- uint8_t ( *GetBatteryLevel )( void );
-}LoRaMacCallback_t;
-
-/*!
- * \brief LoRaMAC layer initialization
- *
- * \details In addition to the initialization of the LoRaMAC layer, this
- * function initializes the callback primitives of the MCPS and
- * MLME services. Every data field of \ref LoRaMacPrimitives_t must be
- * set to a valid callback function.
- *
- * \param [IN] events - Pointer to a structure defining the LoRaMAC
- * event functions. Refer to \ref LoRaMacPrimitives_t.
- *
- * \param [IN] events - Pointer to a structure defining the LoRaMAC
- * callback functions. Refer to \ref LoRaMacCallback_t.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
- */
-LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks );
-
-/*!
- * \brief Queries the LoRaMAC if it is possible to send the next frame with
- * a given payload size. The LoRaMAC takes scheduled MAC commands into
- * account and reports, when the frame can be send or not.
- *
- * \param [IN] size - Size of applicative payload to be send next
- *
- * \param [OUT] txInfo - The structure \ref LoRaMacTxInfo_t contains
- * information about the actual maximum payload possible
- * ( according to the configured datarate or the next
- * datarate according to ADR ), and the maximum frame
- * size, taking the scheduled MAC commands into account.
- *
- * \retval LoRaMacStatus_t Status of the operation. When the parameters are
- * not valid, the function returns \ref LORAMAC_STATUS_PARAMETER_INVALID.
- * In case of a length error caused by the applicative payload size, the
- * function returns LORAMAC_STATUS_LENGTH_ERROR. In case of a length error
- * due to additional MAC commands in the queue, the function returns
- * LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR. In case the query is valid, and
- * the LoRaMAC is able to send the frame, the function returns LORAMAC_STATUS_OK. *
- */
-LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo );
-
-/*!
- * \brief LoRaMAC channel add service
- *
- * \details Adds a new channel to the channel list and activates the id in
- * the channel mask. For the US915 band, all channels are enabled
- * by default. It is not possible to activate less than 6 125 kHz
- * channels.
- *
- * \param [IN] id - Id of the channel. Possible values are:
- *
- * 0-15 for EU868
- * 0-72 for US915
- *
- * \param [IN] params - Channel parameters to set.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
- */
-LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
-
-/*!
- * \brief LoRaMAC channel remove service
- *
- * \details Deactivates the id in the channel mask.
- *
- * \param [IN] id - Id of the channel.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
- */
-LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
-
-/*!
- * \brief LoRaMAC multicast channel link service
- *
- * \details Links a multicast channel into the linked list.
- *
- * \param [IN] channelParam - Multicast channel parameters to link.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
- */
-LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam );
-
-/*!
- * \brief LoRaMAC multicast channel unlink service
- *
- * \details Unlinks a multicast channel from the linked list.
- *
- * \param [IN] channelParam - Multicast channel parameters to unlink.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
- */
-LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam );
-
-/*!
- * \brief LoRaMAC MIB-Get
- *
- * \details The mac information base service to get attributes of the LoRaMac
- * layer.
- *
- * The following code-snippet shows how to use the API to get the
- * parameter AdrEnable, defined by the enumeration type
- * \ref MIB_ADR.
- * \code
- * MibRequestConfirm_t mibReq;
- * mibReq.Type = MIB_ADR;
- *
- * if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK )
- * {
- * // LoRaMAC updated the parameter mibParam.AdrEnable
- * }
- * \endcode
- *
- * \param [IN] mibRequest - MIB-GET-Request to perform. Refer to \ref MibRequestConfirm_t.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
- */
-LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
-
-/*!
- * \brief LoRaMAC MIB-Set
- *
- * \details The mac information base service to set attributes of the LoRaMac
- * layer.
- *
- * The following code-snippet shows how to use the API to set the
- * parameter AdrEnable, defined by the enumeration type
- * \ref MIB_ADR.
- *
- * \code
- * MibRequestConfirm_t mibReq;
- * mibReq.Type = MIB_ADR;
- * mibReq.Param.AdrEnable = true;
- *
- * if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK )
- * {
- * // LoRaMAC updated the parameter
- * }
- * \endcode
- *
- * \param [IN] mibRequest - MIB-SET-Request to perform. Refer to \ref MibRequestConfirm_t.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID.
- */
-LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet );
-
-/*!
- * \brief LoRaMAC MLME-Request
- *
- * \details The Mac layer management entity handles management services. The
- * following code-snippet shows how to use the API to perform a
- * network join request.
- *
- * \code
- * static uint8_t DevEui[] =
- * {
- * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- * };
- * static uint8_t AppEui[] =
- * {
- * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- * };
- * static uint8_t AppKey[] =
- * {
- * 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
- * 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
- * };
- *
- * MlmeReq_t mlmeReq;
- * mlmeReq.Type = MLME_JOIN;
- * mlmeReq.Req.Join.DevEui = DevEui;
- * mlmeReq.Req.Join.AppEui = AppEui;
- * mlmeReq.Req.Join.AppKey = AppKey;
- *
- * if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
- * {
- * // Service started successfully. Waiting for the Mlme-Confirm event
- * }
- * \endcode
- *
- * \param [IN] mlmeRequest - MLME-Request to perform. Refer to \ref MlmeReq_t.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID,
- * \ref LORAMAC_STATUS_NO_NETWORK_JOINED,
- * \ref LORAMAC_STATUS_LENGTH_ERROR,
- * \ref LORAMAC_STATUS_DEVICE_OFF.
- */
-LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest );
-
-/*!
- * \brief LoRaMAC MCPS-Request
- *
- * \details The Mac Common Part Sublayer handles data services. The following
- * code-snippet shows how to use the API to send an unconfirmed
- * LoRaMAC frame.
- *
- * \code
- * uint8_t myBuffer[] = { 1, 2, 3 };
- *
- * McpsReq_t mcpsReq;
- * mcpsReq.Type = MCPS_UNCONFIRMED;
- * mcpsReq.Req.Unconfirmed.fPort = 1;
- * mcpsReq.Req.Unconfirmed.fBuffer = myBuffer;
- * mcpsReq.Req.Unconfirmed.fBufferSize = sizeof( myBuffer );
- *
- * if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
- * {
- * // Service started successfully. Waiting for the MCPS-Confirm event
- * }
- * \endcode
- *
- * \param [IN] mcpsRequest - MCPS-Request to perform. Refer to \ref McpsReq_t.
- *
- * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
- * \ref LORAMAC_STATUS_OK,
- * \ref LORAMAC_STATUS_BUSY,
- * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
- * \ref LORAMAC_STATUS_PARAMETER_INVALID,
- * \ref LORAMAC_STATUS_NO_NETWORK_JOINED,
- * \ref LORAMAC_STATUS_LENGTH_ERROR,
- * \ref LORAMAC_STATUS_DEVICE_OFF.
- */
-LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest );
-
-/*! \} defgroup LORAMAC */
-
-#endif // __LORAMAC_H__
+/*!
+ * \file LoRaMac.h
+ *
+ * \brief LoRa MAC layer implementation
+ *
+ * \copyright Revised BSD License, see section \ref LICENSE.
+ *
+ * \code
+ * ______ _
+ * / _____) _ | |
+ * ( (____ _____ ____ _| |_ _____ ____| |__
+ * \____ \| ___ | (_ _) ___ |/ ___) _ \
+ * _____) ) ____| | | || |_| ____( (___| | | |
+ * (______/|_____)_|_|_| \__)_____)\____)_| |_|
+ * (C)2013 Semtech
+ *
+ * ___ _____ _ ___ _ _____ ___ ___ ___ ___
+ * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
+ * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
+ * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
+ * embedded.connectivity.solutions===============
+ *
+ * \endcode
+ *
+ * \author Miguel Luis ( Semtech )
+ *
+ * \author Gregory Cristian ( Semtech )
+ *
+ * \author Daniel Jäckle ( STACKFORCE )
+ *
+ * \defgroup LORAMAC LoRa MAC layer implementation
+ * This module specifies the API implementation of the LoRaMAC layer.
+ * This is a placeholder for a detailed description of the LoRaMac
+ * layer and the supported features.
+ * \{
+ *
+ * \example classA/LoRaMote/main.c
+ * LoRaWAN class A application example for the LoRaMote.
+ *
+ * \example classB/LoRaMote/main.c
+ * LoRaWAN class B application example for the LoRaMote.
+ *
+ * \example classC/LoRaMote/main.c
+ * LoRaWAN class C application example for the LoRaMote.
+ */
+#ifndef __LORAMAC_H__
+#define __LORAMAC_H__
+
+// Includes board dependent definitions such as channels frequencies
+#include "LoRaMac-board.h"
+
+/*!
+ * Beacon interval in us
+ */
+#define BEACON_INTERVAL 128000000
+
+/*!
+ * Class A&B receive delay 1 in us
+ */
+#define RECEIVE_DELAY1 1000000
+
+/*!
+ * Class A&B receive delay 2 in us
+ */
+#define RECEIVE_DELAY2 2000000
+
+/*!
+ * Join accept receive delay 1 in us
+ */
+#define JOIN_ACCEPT_DELAY1 5000000
+
+/*!
+ * Join accept receive delay 2 in us
+ */
+#define JOIN_ACCEPT_DELAY2 6000000
+
+/*!
+ * Class A&B maximum receive window delay in us
+ */
+#define MAX_RX_WINDOW 3000000
+
+/*!
+ * Maximum allowed gap for the FCNT field
+ */
+#define MAX_FCNT_GAP 16384
+
+/*!
+ * ADR acknowledgement counter limit
+ */
+#define ADR_ACK_LIMIT 64
+
+/*!
+ * Number of ADR acknowledgement requests before returning to default datarate
+ */
+#define ADR_ACK_DELAY 32
+
+/*!
+ * Number of seconds after the start of the second reception window without
+ * receiving an acknowledge.
+ * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
+ */
+#define ACK_TIMEOUT 2000000
+
+/*!
+ * Random number of seconds after the start of the second reception window without
+ * receiving an acknowledge
+ * AckTimeout = \ref ACK_TIMEOUT + Random( -\ref ACK_TIMEOUT_RND, \ref ACK_TIMEOUT_RND )
+ */
+#define ACK_TIMEOUT_RND 1000000
+
+/*!
+ * Check the Mac layer state every MAC_STATE_CHECK_TIMEOUT in us
+ */
+#define MAC_STATE_CHECK_TIMEOUT 1000000
+
+/*!
+ * Maximum number of times the MAC layer tries to get an acknowledge.
+ */
+#define MAX_ACK_RETRIES 8
+
+/*!
+ * RSSI free threshold [dBm]
+ */
+#define RSSI_FREE_TH ( int8_t )( -90 )
+
+/*!
+ * Frame direction definition for up-link communications
+ */
+#define UP_LINK 0
+
+/*!
+ * Frame direction definition for down-link communications
+ */
+#define DOWN_LINK 1
+
+/*!
+ * Sets the length of the LoRaMAC footer field.
+ * Mainly indicates the MIC field length
+ */
+#define LORAMAC_MFR_LEN 4
+
+/*!
+ * Syncword for Private LoRa networks
+ */
+#define LORA_MAC_PRIVATE_SYNCWORD 0x12
+
+/*!
+ * Syncword for Public LoRa networks
+ */
+#define LORA_MAC_PUBLIC_SYNCWORD 0x34
+
+
+/*!
+ * Sets the size of the Join Retransmission duty cycle
+ * table
+ */
+#define JOIN_NB_RETRANSMISSION_DCYCLES 3
+
+ /*!
+ * LoRaMac internal state
+ */
+//uint32_t LoRaMacState;
+
+/*!
+ * LoRaWAN devices classes definition
+ */
+typedef enum eDeviceClass
+{
+ /*!
+ * LoRaWAN device class A
+ *
+ * LoRaWAN Specification V1.0, chapter 3ff
+ */
+ CLASS_A,
+ /*!
+ * LoRaWAN device class B
+ *
+ * LoRaWAN Specification V1.0, chapter 8ff
+ */
+ CLASS_B,
+ /*!
+ * LoRaWAN device class C
+ *
+ * LoRaWAN Specification V1.0, chapter 17ff
+ */
+ CLASS_C,
+}DeviceClass_t;
+
+/*!
+ * LoRaMAC channels parameters definition
+ */
+typedef union uDrRange
+{
+ /*!
+ * Byte-access to the bits
+ */
+ int8_t Value;
+ /*!
+ * Structure to store the minimum and the maximum datarate
+ */
+ struct sFields
+ {
+ /*!
+ * Minimum data rate
+ *
+ * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
+ *
+ * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4]
+ */
+ int8_t Min : 4;
+ /*!
+ * Maximum data rate
+ *
+ * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
+ *
+ * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4]
+ */
+ int8_t Max : 4;
+ }Fields;
+}DrRange_t;
+
+/*!
+ * LoRaMAC band parameters definition
+ */
+typedef struct sBand
+{
+ /*!
+ * Duty cycle
+ */
+ uint16_t DCycle;
+ /*!
+ * Maximum Tx power
+ */
+ int8_t TxMaxPower;
+ /*!
+ * Time stamp of the last Tx frame
+ */
+ TimerTime_t LastTxDoneTime;
+ /*!
+ * Holds the time where the device is off
+ */
+ TimerTime_t TimeOff;
+}Band_t;
+
+/*!
+ * LoRaMAC channel definition
+ */
+typedef struct sChannelParams
+{
+ /*!
+ * Frequency in Hz
+ */
+ uint32_t Frequency;
+ /*!
+ * Data rate definition
+ */
+ DrRange_t DrRange;
+ /*!
+ * Band index
+ */
+ uint8_t Band;
+}ChannelParams_t;
+
+/*!
+ * LoRaMAC receive window 2 channel parameters
+ */
+typedef struct sRx2ChannelParams
+{
+ /*!
+ * Frequency in Hz
+ */
+ uint32_t Frequency;
+ /*!
+ * Data rate
+ *
+ * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
+ *
+ * US915 - [DR_8, DR_9, DR_10, DR_11, DR_12, DR_13]
+ */
+ uint8_t Datarate;
+}Rx2ChannelParams_t;
+
+/*!
+ * LoRaMAC multicast channel parameter
+ */
+typedef struct sMulticastParams
+{
+ /*!
+ * Address
+ */
+ uint32_t Address;
+ /*!
+ * Network session key
+ */
+ uint8_t NwkSKey[16];
+ /*!
+ * Application session key
+ */
+ uint8_t AppSKey[16];
+ /*!
+ * Downlink counter
+ */
+ uint32_t DownLinkCounter;
+ /*!
+ * Reference pointer to the next multicast channel parameters in the list
+ */
+ struct sMulticastParams *Next;
+}MulticastParams_t;
+
+/*!
+ * LoRaMAC frame types
+ *
+ * LoRaWAN Specification V1.0, chapter 4.2.1, table 1
+ */
+typedef enum eLoRaMacFrameType
+{
+ /*!
+ * LoRaMAC join request frame
+ */
+ FRAME_TYPE_JOIN_REQ = 0x00,
+ /*!
+ * LoRaMAC join accept frame
+ */
+ FRAME_TYPE_JOIN_ACCEPT = 0x01,
+ /*!
+ * LoRaMAC unconfirmed up-link frame
+ */
+ FRAME_TYPE_DATA_UNCONFIRMED_UP = 0x02,
+ /*!
+ * LoRaMAC unconfirmed down-link frame
+ */
+ FRAME_TYPE_DATA_UNCONFIRMED_DOWN = 0x03,
+ /*!
+ * LoRaMAC confirmed up-link frame
+ */
+ FRAME_TYPE_DATA_CONFIRMED_UP = 0x04,
+ /*!
+ * LoRaMAC confirmed down-link frame
+ */
+ FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05,
+ /*!
+ * LoRaMAC RFU frame
+ */
+ FRAME_TYPE_RFU = 0x06,
+ /*!
+ * LoRaMAC proprietary frame
+ */
+ FRAME_TYPE_PROPRIETARY = 0x07,
+}LoRaMacFrameType_t;
+
+/*!
+ * LoRaMAC mote MAC commands
+ *
+ * LoRaWAN Specification V1.0, chapter 5, table 4
+ */
+typedef enum eLoRaMacMoteCmd
+{
+ /*!
+ * LinkCheckReq
+ */
+ MOTE_MAC_LINK_CHECK_REQ = 0x02,
+ /*!
+ * LinkADRAns
+ */
+ MOTE_MAC_LINK_ADR_ANS = 0x03,
+ /*!
+ * DutyCycleAns
+ */
+ MOTE_MAC_DUTY_CYCLE_ANS = 0x04,
+ /*!
+ * RXParamSetupAns
+ */
+ MOTE_MAC_RX_PARAM_SETUP_ANS = 0x05,
+ /*!
+ * DevStatusAns
+ */
+ MOTE_MAC_DEV_STATUS_ANS = 0x06,
+ /*!
+ * NewChannelAns
+ */
+ MOTE_MAC_NEW_CHANNEL_ANS = 0x07,
+ /*!
+ * RXTimingSetupAns
+ */
+ MOTE_MAC_RX_TIMING_SETUP_ANS = 0x08,
+}LoRaMacMoteCmd_t;
+
+/*!
+ * LoRaMAC server MAC commands
+ *
+ * LoRaWAN Specification V1.0, chapter 5, table 4
+ */
+typedef enum eLoRaMacSrvCmd
+{
+ /*!
+ * LinkCheckAns
+ */
+ SRV_MAC_LINK_CHECK_ANS = 0x02,
+ /*!
+ * LinkADRReq
+ */
+ SRV_MAC_LINK_ADR_REQ = 0x03,
+ /*!
+ * DutyCycleReq
+ */
+ SRV_MAC_DUTY_CYCLE_REQ = 0x04,
+ /*!
+ * RXParamSetupReq
+ */
+ SRV_MAC_RX_PARAM_SETUP_REQ = 0x05,
+ /*!
+ * DevStatusReq
+ */
+ SRV_MAC_DEV_STATUS_REQ = 0x06,
+ /*!
+ * NewChannelReq
+ */
+ SRV_MAC_NEW_CHANNEL_REQ = 0x07,
+ /*!
+ * RXTimingSetupReq
+ */
+ SRV_MAC_RX_TIMING_SETUP_REQ = 0x08,
+}LoRaMacSrvCmd_t;
+
+/*!
+ * LoRaMAC Battery level indicator
+ */
+typedef enum eLoRaMacBatteryLevel
+{
+ /*!
+ * External power source
+ */
+ BAT_LEVEL_EXT_SRC = 0x00,
+ /*!
+ * Battery level empty
+ */
+ BAT_LEVEL_EMPTY = 0x01,
+ /*!
+ * Battery level full
+ */
+ BAT_LEVEL_FULL = 0xFE,
+ /*!
+ * Battery level - no measurement available
+ */
+ BAT_LEVEL_NO_MEASURE = 0xFF,
+}LoRaMacBatteryLevel_t;
+
+/*!
+ * LoRaMAC header field definition (MHDR field)
+ *
+ * LoRaWAN Specification V1.0, chapter 4.2
+ */
+typedef union uLoRaMacHeader
+{
+ /*!
+ * Byte-access to the bits
+ */
+ uint8_t Value;
+ /*!
+ * Structure containing single access to header bits
+ */
+ struct sHdrBits
+ {
+ /*!
+ * Major version
+ */
+ uint8_t Major : 2;
+ /*!
+ * RFU
+ */
+ uint8_t RFU : 3;
+ /*!
+ * Message type
+ */
+ uint8_t MType : 3;
+ }Bits;
+}LoRaMacHeader_t;
+
+/*!
+ * LoRaMAC frame control field definition (FCtrl)
+ *
+ * LoRaWAN Specification V1.0, chapter 4.3.1
+ */
+typedef union uLoRaMacFrameCtrl
+{
+ /*!
+ * Byte-access to the bits
+ */
+ uint8_t Value;
+ /*!
+ * Structure containing single access to bits
+ */
+ struct sCtrlBits
+ {
+ /*!
+ * Frame options length
+ */
+ uint8_t FOptsLen : 4;
+ /*!
+ * Frame pending bit
+ */
+ uint8_t FPending : 1;
+ /*!
+ * Message acknowledge bit
+ */
+ uint8_t Ack : 1;
+ /*!
+ * ADR acknowledgment request bit
+ */
+ uint8_t AdrAckReq : 1;
+ /*!
+ * ADR control in frame header
+ */
+ uint8_t Adr : 1;
+ }Bits;
+}LoRaMacFrameCtrl_t;
+
+/*!
+ * Enumeration containing the status of the operation of a MAC service
+ */
+typedef enum eLoRaMacEventInfoStatus
+{
+ /*!
+ * Service performed successfully
+ */
+ LORAMAC_EVENT_INFO_STATUS_OK = 0,
+ /*!
+ * An error occured during the execution of the service
+ */
+ LORAMAC_EVENT_INFO_STATUS_ERROR,
+ /*!
+ * A Tx timeouit occured
+ */
+ LORAMAC_EVENT_INFO_STATUS_TX_TIMEOUT,
+ /*!
+ * An Rx timeout occured on receive window 2
+ */
+ LORAMAC_EVENT_INFO_STATUS_RX2_TIMEOUT,
+ /*!
+ * An Rx error occured on receive window 2
+ */
+ LORAMAC_EVENT_INFO_STATUS_RX2_ERROR,
+ /*!
+ * An error occured in the join procedure
+ */
+ LORAMAC_EVENT_INFO_STATUS_JOIN_FAIL,
+ /*!
+ * A frame with an invalid downlink counter was received. The
+ * downlink counter of the frame was equal to the local copy
+ * of the downlink counter of the node.
+ */
+ LORAMAC_EVENT_INFO_STATUS_DOWNLINK_REPEATED,
+ /*!
+ * The node has lost MAX_FCNT_GAP or more frames.
+ */
+ LORAMAC_EVENT_INFO_STATUS_DOWNLINK_TOO_MANY_FRAMES_LOSS,
+ /*!
+ * An address error occured
+ */
+ LORAMAC_EVENT_INFO_STATUS_ADDRESS_FAIL,
+ /*!
+ * message integrity check failure
+ */
+ LORAMAC_EVENT_INFO_STATUS_MIC_FAIL,
+}LoRaMacEventInfoStatus_t;
+
+/*!
+ * LoRaMac tx/rx operation state
+ */
+typedef union eLoRaMacFlags_t
+{
+ /*!
+ * Byte-access to the bits
+ */
+ uint8_t Value;
+ /*!
+ * Structure containing single access to bits
+ */
+ struct sMacFlagBits
+ {
+ /*!
+ * MCPS-Req pending
+ */
+ uint8_t McpsReq : 1;
+ /*!
+ * MCPS-Ind pending
+ */
+ uint8_t McpsInd : 1;
+ /*!
+ * MLME-Req pending
+ */
+ uint8_t MlmeReq : 1;
+ /*!
+ * MAC cycle done
+ */
+ uint8_t MacDone : 1;
+ }Bits;
+}LoRaMacFlags_t;
+
+/*!
+ *
+ * \brief LoRaMAC data services
+ *
+ * \details The following table list the primitives which are supported by the
+ * specific MAC data service:
+ *
+ * Name | Request | Indication | Response | Confirm
+ * --------------------- | :-----: | :--------: | :------: | :-----:
+ * \ref MCPS_UNCONFIRMED | YES | YES | NO | YES
+ * \ref MCPS_CONFIRMED | YES | YES | NO | YES
+ * \ref MCPS_MULTICAST | NO | YES | NO | NO
+ * \ref MCPS_PROPRIETARY | YES | YES | NO | YES
+ *
+ * The following table provides links to the function implementations of the
+ * related MCPS primitives:
+ *
+ * Primitive | Function
+ * ---------------- | :---------------------:
+ * MCPS-Request | \ref LoRaMacMlmeRequest
+ * MCPS-Confirm | MacMcpsConfirm in \ref LoRaMacPrimitives_t
+ * MCPS-Indication | MacMcpsIndication in \ref LoRaMacPrimitives_t
+ */
+typedef enum eMcps
+{
+ /*!
+ * Unconfirmed LoRaMAC frame
+ */
+ MCPS_UNCONFIRMED,
+ /*!
+ * Confirmed LoRaMAC frame
+ */
+ MCPS_CONFIRMED,
+ /*!
+ * Multicast LoRaMAC frame
+ */
+ MCPS_MULTICAST,
+ /*!
+ * Proprietary frame
+ */
+ MCPS_PROPRIETARY,
+}Mcps_t;
+
+/*!
+ * LoRaMAC MCPS-Request for an unconfirmed frame
+ */
+typedef struct sMcpsReqUnconfirmed
+{
+ /*!
+ * Frame port field. Must be set if the payload is not empty. Use the
+ * application specific frame port values: [1...223]
+ *
+ * LoRaWAN Specification V1.0, chapter 4.3.2
+ */
+ uint8_t fPort;
+ /*!
+ * Pointer to the buffer of the frame payload
+ */
+ void *fBuffer;
+ /*!
+ * Size of the frame payload
+ */
+ uint16_t fBufferSize;
+ /*!
+ * Uplink datarate, if ADR is off
+ */
+ int8_t Datarate;
+}McpsReqUnconfirmed_t;
+
+/*!
+ * LoRaMAC MCPS-Request for a confirmed frame
+ */
+typedef struct sMcpsReqConfirmed
+{
+ /*!
+ * Frame port field. Must be set if the payload is not empty. Use the
+ * application specific frame port values: [1...223]
+ *
+ * LoRaWAN Specification V1.0, chapter 4.3.2
+ */
+ uint8_t fPort;
+ /*!
+ * Pointer to the buffer of the frame payload
+ */
+ void *fBuffer;
+ /*!
+ * Size of the frame payload
+ */
+ uint16_t fBufferSize;
+ /*!
+ * Uplink datarate, if ADR is off
+ */
+ int8_t Datarate;
+ /*!
+ * Number of trials to transmit the frame, if the LoRaMAC layer did not
+ * receive an acknowledgment. The MAC performs a datarate adaptation,
+ * according to the LoRaWAN Specification V1.0, chapter 18.4, according
+ * to the following table:
+ *
+ * Transmission nb | Data Rate
+ * ----------------|-----------
+ * 1 (first) | DR
+ * 2 | DR
+ * 3 | max(DR-1,0)
+ * 4 | max(DR-1,0)
+ * 5 | max(DR-2,0)
+ * 6 | max(DR-2,0)
+ * 7 | max(DR-3,0)
+ * 8 | max(DR-3,0)
+ *
+ * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease
+ * the datarate, in case the LoRaMAC layer did not receive an acknowledgment
+ */
+ uint8_t NbTrials;
+}McpsReqConfirmed_t;
+
+/*!
+ * LoRaMAC MCPS-Request for a proprietary frame
+ */
+typedef struct sMcpsReqProprietary
+{
+ /*!
+ * Pointer to the buffer of the frame payload
+ */
+ void *fBuffer;
+ /*!
+ * Size of the frame payload
+ */
+ uint16_t fBufferSize;
+ /*!
+ * Uplink datarate, if ADR is off
+ */
+ int8_t Datarate;
+}McpsReqProprietary_t;
+
+/*!
+ * LoRaMAC MCPS-Request structure
+ */
+typedef struct sMcpsReq
+{
+ /*!
+ * MCPS-Request type
+ */
+ Mcps_t Type;
+
+ /*!
+ * MCPS-Request parameters
+ */
+ union uMcpsParam
+ {
+ /*!
+ * MCPS-Request parameters for an unconfirmed frame
+ */
+ McpsReqUnconfirmed_t Unconfirmed;
+ /*!
+ * MCPS-Request parameters for a confirmed frame
+ */
+ McpsReqConfirmed_t Confirmed;
+ /*!
+ * MCPS-Request parameters for a proprietary frame
+ */
+ McpsReqProprietary_t Proprietary;
+ }Req;
+}McpsReq_t;
+
+/*!
+ * LoRaMAC MCPS-Confirm
+ */
+typedef struct sMcpsConfirm
+{
+ /*!
+ * Holds the previously performed MCPS-Request
+ */
+ Mcps_t McpsRequest;
+ /*!
+ * Status of the operation
+ */
+ LoRaMacEventInfoStatus_t Status;
+ /*!
+ * Uplink datarate
+ */
+ uint8_t Datarate;
+ /*!
+ * Transmission power
+ */
+ int8_t TxPower;
+ /*!
+ * Set if an acknowledgement was received
+ */
+ bool AckReceived;
+ /*!
+ * Provides the number of retransmissions
+ */
+ uint8_t NbRetries;
+ /*!
+ * The transmission time on air of the frame
+ */
+ TimerTime_t TxTimeOnAir;
+ /*!
+ * The uplink counter value related to the frame
+ */
+ uint32_t UpLinkCounter;
+}McpsConfirm_t;
+
+/*!
+ * LoRaMAC MCPS-Indication primitive
+ */
+typedef struct sMcpsIndication
+{
+ /*!
+ * MCPS-Indication type
+ */
+ Mcps_t McpsIndication;
+ /*!
+ * Status of the operation
+ */
+ LoRaMacEventInfoStatus_t Status;
+ /*!
+ * Multicast
+ */
+ uint8_t Multicast;
+ /*!
+ * Application port
+ */
+ uint8_t Port;
+ /*!
+ * Downlink datarate
+ */
+ uint8_t RxDatarate;
+ /*!
+ * Frame pending status
+ */
+ uint8_t FramePending;
+ /*!
+ * Pointer to the received data stream
+ */
+ uint8_t *Buffer;
+ /*!
+ * Size of the received data stream
+ */
+ uint8_t BufferSize;
+ /*!
+ * Indicates, if data is available
+ */
+ bool RxData;
+ /*!
+ * Rssi of the received packet
+ */
+ int16_t Rssi;
+ /*!
+ * Snr of the received packet
+ */
+ uint8_t Snr;
+ /*!
+ * Receive window
+ *
+ * [0: Rx window 1, 1: Rx window 2]
+ */
+ uint8_t RxSlot;
+ /*!
+ * Set if an acknowledgement was received
+ */
+ bool AckReceived;
+ /*!
+ * The downlink counter value for the received frame
+ */
+ uint32_t DownLinkCounter;
+}McpsIndication_t;
+
+/*!
+ * \brief LoRaMAC management services
+ *
+ * \details The following table list the primitives which are supported by the
+ * specific MAC management service:
+ *
+ * Name | Request | Indication | Response | Confirm
+ * --------------------- | :-----: | :--------: | :------: | :-----:
+ * \ref MLME_JOIN | YES | NO | NO | YES
+ * \ref MLME_LINK_CHECK | YES | NO | NO | YES
+ *
+ * The following table provides links to the function implementations of the
+ * related MLME primitives.
+ *
+ * Primitive | Function
+ * ---------------- | :---------------------:
+ * MLME-Request | \ref LoRaMacMlmeRequest
+ * MLME-Confirm | MacMlmeConfirm in \ref LoRaMacPrimitives_t
+ */
+typedef enum eMlme
+{
+ /*!
+ * Initiates the Over-the-Air activation
+ *
+ * LoRaWAN Specification V1.0, chapter 6.2
+ */
+ MLME_JOIN,
+ /*!
+ * LinkCheckReq - Connectivity validation
+ *
+ * LoRaWAN Specification V1.0, chapter 5, table 4
+ */
+ MLME_LINK_CHECK,
+}Mlme_t;
+
+/*!
+ * LoRaMAC MLME-Request for the join service
+ */
+typedef struct sMlmeReqJoin
+{
+ /*!
+ * Globally unique end-device identifier
+ *
+ * LoRaWAN Specification V1.0, chapter 6.2.1
+ */
+ uint8_t *DevEui;
+ /*!
+ * Application identifier
+ *
+ * LoRaWAN Specification V1.0, chapter 6.1.2
+ */
+ uint8_t *AppEui;
+ /*!
+ * AES-128 application key
+ *
+ * LoRaWAN Specification V1.0, chapter 6.2.2
+ */
+ uint8_t *AppKey;
+}MlmeReqJoin_t;
+
+/*!
+ * LoRaMAC MLME-Request structure
+ */
+typedef struct sMlmeReq
+{
+ /*!
+ * MLME-Request type
+ */
+ Mlme_t Type;
+
+ /*!
+ * MLME-Request parameters
+ */
+ union uMlmeParam
+ {
+ /*!
+ * MLME-Request parameters for a join request
+ */
+ MlmeReqJoin_t Join;
+ }Req;
+}MlmeReq_t;
+
+/*!
+ * LoRaMAC MLME-Confirm primitive
+ */
+typedef struct sMlmeConfirm
+{
+ /*!
+ * Holds the previously performed MLME-Request
+ */
+ Mlme_t MlmeRequest;
+ /*!
+ * Status of the operation
+ */
+ LoRaMacEventInfoStatus_t Status;
+ /*!
+ * The transmission time on air of the frame
+ */
+ TimerTime_t TxTimeOnAir;
+ /*!
+ * Demodulation margin. Contains the link margin [dB] of the last
+ * successfully received LinkCheckReq
+ */
+ uint8_t DemodMargin;
+ /*!
+ * Number of gateways which received the last LinkCheckReq
+ */
+ uint8_t NbGateways;
+}MlmeConfirm_t;
+
+/*!
+ * LoRa Mac Information Base (MIB)
+ *
+ * The following table lists the MIB parameters and the related attributes:
+ *
+ * Attribute | Get | Set
+ * --------------------------------- | :-: | :-:
+ * \ref MIB_DEVICE_CLASS | YES | YES
+ * \ref MIB_NETWORK_JOINED | YES | YES
+ * \ref MIB_ADR | YES | YES
+ * \ref MIB_NET_ID | YES | YES
+ * \ref MIB_DEV_ADDR | YES | YES
+ * \ref MIB_NWK_SKEY | YES | YES
+ * \ref MIB_APP_SKEY | YES | YES
+ * \ref MIB_PUBLIC_NETWORK | YES | YES
+ * \ref MIB_REPEATER_SUPPORT | YES | YES
+ * \ref MIB_CHANNELS | YES | NO
+ * \ref MIB_RX2_CHANNEL | YES | YES
+ * \ref MIB_CHANNELS_MASK | YES | YES
+ * \ref MIB_CHANNELS_NB_REP | YES | YES
+ * \ref MIB_MAX_RX_WINDOW_DURATION | YES | YES
+ * \ref MIB_RECEIVE_DELAY_1 | YES | YES
+ * \ref MIB_RECEIVE_DELAY_2 | YES | YES
+ * \ref MIB_JOIN_ACCEPT_DELAY_1 | YES | YES
+ * \ref MIB_JOIN_ACCEPT_DELAY_2 | YES | YES
+ * \ref MIB_CHANNELS_DATARATE | YES | YES
+ * \ref MIB_CHANNELS_DEFAULT_DATARATE| YES | YES
+ * \ref MIB_CHANNELS_TX_POWER | YES | YES
+ * \ref MIB_UPLINK_COUNTER | YES | YES
+ * \ref MIB_DOWNLINK_COUNTER | YES | YES
+ * \ref MIB_MULTICAST_CHANNEL | YES | NO
+ *
+ * The following table provides links to the function implementations of the
+ * related MIB primitives:
+ *
+ * Primitive | Function
+ * ---------------- | :---------------------:
+ * MIB-Set | \ref LoRaMacMibSetRequestConfirm
+ * MIB-Get | \ref LoRaMacMibGetRequestConfirm
+ */
+typedef enum eMib
+{
+ /*!
+ * LoRaWAN device class
+ *
+ * LoRaWAN Specification V1.0
+ */
+ MIB_DEVICE_CLASS,
+ /*!
+ * LoRaWAN Network joined attribute
+ *
+ * LoRaWAN Specification V1.0
+ */
+ MIB_NETWORK_JOINED,
+ /*!
+ * Adaptive data rate
+ *
+ * LoRaWAN Specification V1.0, chapter 4.3.1.1
+ *
+ * [true: ADR enabled, false: ADR disabled]
+ */
+ MIB_ADR,
+ /*!
+ * Network identifier
+ *
+ * LoRaWAN Specification V1.0, chapter 6.2.5
+ */
+ MIB_NET_ID,
+ /*!
+ * End-device address
+ *
+ * LoRaWAN Specification V1.0, chapter 6.1.2
+ */
+ MIB_DEV_ADDR,
+ /*!
+ * Network session key
+ *
+ * LoRaWAN Specification V1.0, chapter 6.1.3
+ */
+ MIB_NWK_SKEY,
+ /*!
+ * Application session key
+ *
+ * LoRaWAN Specification V1.0, chapter 6.1.4
+ */
+ MIB_APP_SKEY,
+ /*!
+ * Set the network type to public or private
+ *
+ * LoRaWAN Specification V1.0, chapter 7
+ *
+ * [true: public network, false: private network]
+ */
+ MIB_PUBLIC_NETWORK,
+ /*!
+ * Support the operation with repeaters
+ *
+ * LoRaWAN Specification V1.0, chapter 7
+ *
+ * [true: repeater support enabled, false: repeater support disabled]
+ */
+ MIB_REPEATER_SUPPORT,
+ /*!
+ * Communication channels. A get request will return a
+ * pointer which references the first entry of the channel list. The
+ * list is of size LORA_MAX_NB_CHANNELS
+ *
+ * LoRaWAN Specification V1.0, chapter 7
+ */
+ MIB_CHANNELS,
+ /*!
+ * Set receive window 2 channel
+ *
+ * LoRaWAN Specification V1.0, chapter 3.3.2
+ */
+ MIB_RX2_CHANNEL,
+ /*!
+ * LoRaWAN channels mask
+ *
+ * LoRaWAN Specification V1.0, chapter 5.2
+ */
+ MIB_CHANNELS_MASK,
+ /*!
+ * Set the number of repetitions on a channel
+ *
+ * LoRaWAN Specification V1.0, chapter 5.2
+ */
+ MIB_CHANNELS_NB_REP,
+ /*!
+ * Maximum receive window duration in [us]
+ *
+ * LoRaWAN Specification V1.0, chapter 3.3.3
+ */
+ MIB_MAX_RX_WINDOW_DURATION,
+ /*!
+ * Receive delay 1 in [us]
+ *
+ * LoRaWAN Specification V1.0, chapter 6
+ */
+ MIB_RECEIVE_DELAY_1,
+ /*!
+ * Receive delay 2 in [us]
+ *
+ * LoRaWAN Specification V1.0, chapter 6
+ */
+ MIB_RECEIVE_DELAY_2,
+ /*!
+ * Join accept delay 1 in [us]
+ *
+ * LoRaWAN Specification V1.0, chapter 6
+ */
+ MIB_JOIN_ACCEPT_DELAY_1,
+ /*!
+ * Join accept delay 2 in [us]
+ *
+ * LoRaWAN Specification V1.0, chapter 6
+ */
+ MIB_JOIN_ACCEPT_DELAY_2,
+ /*!
+ * Default Data rate of a channel
+ *
+ * LoRaWAN Specification V1.0, chapter 7
+ *
+ * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
+ *
+ * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13]
+ */
+ MIB_CHANNELS_DEFAULT_DATARATE,
+ /*!
+ * Data rate of a channel
+ *
+ * LoRaWAN Specification V1.0, chapter 7
+ *
+ * EU868 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_5, DR_6, DR_7]
+ *
+ * US915 - [DR_0, DR_1, DR_2, DR_3, DR_4, DR_8, DR_9, DR_10, DR_11, DR_12, DR_13]
+ */
+ MIB_CHANNELS_DATARATE,
+ /*!
+ * Transmission power of a channel
+ *
+ * LoRaWAN Specification V1.0, chapter 7
+ *
+ * EU868 - [TX_POWER_20_DBM, TX_POWER_14_DBM, TX_POWER_11_DBM,
+ * TX_POWER_08_DBM, TX_POWER_05_DBM, TX_POWER_02_DBM]
+ *
+ * US915 - [TX_POWER_30_DBM, TX_POWER_28_DBM, TX_POWER_26_DBM,
+ * TX_POWER_24_DBM, TX_POWER_22_DBM, TX_POWER_20_DBM,
+ * TX_POWER_18_DBM, TX_POWER_14_DBM, TX_POWER_12_DBM,
+ * TX_POWER_10_DBM]
+ */
+ MIB_CHANNELS_TX_POWER,
+ /*!
+ * LoRaWAN Up-link counter
+ *
+ * LoRaWAN Specification V1.0, chapter 4.3.1.5
+ */
+ MIB_UPLINK_COUNTER,
+ /*!
+ * LoRaWAN Down-link counter
+ *
+ * LoRaWAN Specification V1.0, chapter 4.3.1.5
+ */
+ MIB_DOWNLINK_COUNTER,
+ /*!
+ * Multicast channels. A get request will return a pointer to the first
+ * entry of the multicast channel linked list. If the pointer is equal to
+ * NULL, the list is empty.
+ */
+ MIB_MULTICAST_CHANNEL,
+}Mib_t;
+
+/*!
+ * LoRaMAC MIB parameters
+ */
+typedef union uMibParam
+{
+ /*!
+ * LoRaWAN device class
+ *
+ * Related MIB type: \ref MIB_DEVICE_CLASS
+ */
+ DeviceClass_t Class;
+ /*!
+ * LoRaWAN network joined attribute
+ *
+ * Related MIB type: \ref MIB_NETWORK_JOINED
+ */
+ bool IsNetworkJoined;
+ /*!
+ * Activation state of ADR
+ *
+ * Related MIB type: \ref MIB_ADR
+ */
+ bool AdrEnable;
+ /*!
+ * Network identifier
+ *
+ * Related MIB type: \ref MIB_NET_ID
+ */
+ uint32_t NetID;
+ /*!
+ * End-device address
+ *
+ * Related MIB type: \ref MIB_DEV_ADDR
+ */
+ uint32_t DevAddr;
+ /*!
+ * Network session key
+ *
+ * Related MIB type: \ref MIB_NWK_SKEY
+ */
+ uint8_t *NwkSKey;
+ /*!
+ * Application session key
+ *
+ * Related MIB type: \ref MIB_APP_SKEY
+ */
+ uint8_t *AppSKey;
+ /*!
+ * Enable or disable a public network
+ *
+ * Related MIB type: \ref MIB_PUBLIC_NETWORK
+ */
+ bool EnablePublicNetwork;
+ /*!
+ * Enable or disable repeater support
+ *
+ * Related MIB type: \ref MIB_REPEATER_SUPPORT
+ */
+ bool EnableRepeaterSupport;
+ /*!
+ * LoRaWAN Channel
+ *
+ * Related MIB type: \ref MIB_CHANNELS
+ */
+ ChannelParams_t* ChannelList;
+ /*!
+ * Channel for the receive window 2
+ *
+ * Related MIB type: \ref MIB_RX2_CHANNEL
+ */
+ Rx2ChannelParams_t Rx2Channel;
+ /*!
+ * Channel mask
+ *
+ * Related MIB type: \ref MIB_CHANNELS_MASK
+ */
+ uint16_t* ChannelsMask;
+ /*!
+ * Number of frame repetitions
+ *
+ * Related MIB type: \ref MIB_CHANNELS_NB_REP
+ */
+ uint8_t ChannelNbRep;
+ /*!
+ * Maximum receive window duration
+ *
+ * Related MIB type: \ref MIB_MAX_RX_WINDOW_DURATION
+ */
+ uint32_t MaxRxWindow;
+ /*!
+ * Receive delay 1
+ *
+ * Related MIB type: \ref MIB_RECEIVE_DELAY_1
+ */
+ uint32_t ReceiveDelay1;
+ /*!
+ * Receive delay 2
+ *
+ * Related MIB type: \ref MIB_RECEIVE_DELAY_2
+ */
+ uint32_t ReceiveDelay2;
+ /*!
+ * Join accept delay 1
+ *
+ * Related MIB type: \ref MIB_JOIN_ACCEPT_DELAY_1
+ */
+ uint32_t JoinAcceptDelay1;
+ /*!
+ * Join accept delay 2
+ *
+ * Related MIB type: \ref MIB_JOIN_ACCEPT_DELAY_2
+ */
+ uint32_t JoinAcceptDelay2;
+ /*!
+ * Channels data rate
+ *
+ * Related MIB type: \ref MIB_CHANNELS_DEFAULT_DATARATE
+ */
+ int8_t ChannelsDefaultDatarate;
+ /*!
+ * Channels data rate
+ *
+ * Related MIB type: \ref MIB_CHANNELS_DATARATE
+ */
+ int8_t ChannelsDatarate;
+ /*!
+ * Channels TX power
+ *
+ * Related MIB type: \ref MIB_CHANNELS_TX_POWER
+ */
+ int8_t ChannelsTxPower;
+ /*!
+ * LoRaWAN Up-link counter
+ *
+ * Related MIB type: \ref MIB_UPLINK_COUNTER
+ */
+ uint32_t UpLinkCounter;
+ /*!
+ * LoRaWAN Down-link counter
+ *
+ * Related MIB type: \ref MIB_DOWNLINK_COUNTER
+ */
+ uint32_t DownLinkCounter;
+ /*!
+ * Multicast channel
+ *
+ * Related MIB type: \ref MIB_MULTICAST_CHANNEL
+ */
+ MulticastParams_t* MulticastList;
+}MibParam_t;
+
+/*!
+ * LoRaMAC MIB-RequestConfirm structure
+ */
+typedef struct eMibRequestConfirm
+{
+ /*!
+ * MIB-Request type
+ */
+ Mib_t Type;
+
+ /*!
+ * MLME-RequestConfirm parameters
+ */
+ MibParam_t Param;
+}MibRequestConfirm_t;
+
+/*!
+ * LoRaMAC tx information
+ */
+typedef struct sLoRaMacTxInfo
+{
+ /*!
+ * Defines the size of the applicative payload which can be processed
+ */
+ uint8_t MaxPossiblePayload;
+ /*!
+ * The current payload size, dependent on the current datarate
+ */
+ uint8_t CurrentPayloadSize;
+}LoRaMacTxInfo_t;
+
+/*!
+ * LoRaMAC Status
+ */
+typedef enum eLoRaMacStatus
+{
+ /*!
+ * Service started successfully
+ */
+ LORAMAC_STATUS_OK,
+ /*!
+ * Service not started - LoRaMAC is busy
+ */
+ LORAMAC_STATUS_BUSY,
+ /*!
+ * Service unknown
+ */
+ LORAMAC_STATUS_SERVICE_UNKNOWN,
+ /*!
+ * Service not started - invalid parameter
+ */
+ LORAMAC_STATUS_PARAMETER_INVALID,
+ /*!
+ * Service not started - invalid frequency
+ */
+ LORAMAC_STATUS_FREQUENCY_INVALID,
+ /*!
+ * Service not started - invalid datarate
+ */
+ LORAMAC_STATUS_DATARATE_INVALID,
+ /*!
+ * Service not started - invalid frequency and datarate
+ */
+ LORAMAC_STATUS_FREQ_AND_DR_INVALID,
+ /*!
+ * Service not started - the device is not in a LoRaWAN
+ */
+ LORAMAC_STATUS_NO_NETWORK_JOINED,
+ /*!
+ * Service not started - playload lenght error
+ */
+ LORAMAC_STATUS_LENGTH_ERROR,
+ /*!
+ * Service not started - playload lenght error
+ */
+ LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR,
+ /*!
+ * Service not started - the device is switched off
+ */
+ LORAMAC_STATUS_DEVICE_OFF,
+ /*!
+ * Service not started - transmit duty cycle exceeded
+ */
+ LORAMAC_STATUS_TX_DCYCLE_EXCEEDED,
+}LoRaMacStatus_t;
+
+/*!
+ * LoRaMAC events structure
+ * Used to notify upper layers of MAC events
+ */
+typedef struct sLoRaMacPrimitives
+{
+ /*!
+ * \brief MCPS-Confirm primitive
+ *
+ * \param [OUT] MCPS-Confirm parameters
+ */
+ void ( *MacMcpsConfirm )( McpsConfirm_t *McpsConfirm );
+ /*!
+ * \brief MCPS-Indication primitive
+ *
+ * \param [OUT] MCPS-Indication parameters
+ */
+ void ( *MacMcpsIndication )( McpsIndication_t *McpsIndication );
+ /*!
+ * \brief MLME-Confirm primitive
+ *
+ * \param [OUT] MLME-Confirm parameters
+ */
+ void ( *MacMlmeConfirm )( MlmeConfirm_t *MlmeConfirm );
+}LoRaMacPrimitives_t;
+
+typedef struct sLoRaMacCallback
+{
+ /*!
+ * \brief Measures the battery level
+ *
+ * \retval Battery level [0: node is connected to an external
+ * power source, 1..254: battery level, where 1 is the minimum
+ * and 254 is the maximum value, 255: the node was not able
+ * to measure the battery level]
+ */
+ uint8_t ( *GetBatteryLevel )( void );
+}LoRaMacCallback_t;
+
+
+/*!
+ * LoRaMAC Retransmission duty cylcle structure
+ * Used for Retransmission back-off duty cycle configuration
+ */
+typedef struct sLoRaMacRetransmissionDCycle
+{
+ TimerTime_t period; // Retransmission period in seconds
+ TimerTime_t onAirTimeMax; // Max on air time in time units used by Radio.TimeOnAir()
+} LoRaMacRetransmissionDCycle_t;
+
+
+/*!
+ * \brief LoRaMAC layer initialization
+ *
+ * \details In addition to the initialization of the LoRaMAC layer, this
+ * function initializes the callback primitives of the MCPS and
+ * MLME services. Every data field of \ref LoRaMacPrimitives_t must be
+ * set to a valid callback function.
+ *
+ * \param [IN] events - Pointer to a structure defining the LoRaMAC
+ * event functions. Refer to \ref LoRaMacPrimitives_t.
+ *
+ * \param [IN] events - Pointer to a structure defining the LoRaMAC
+ * callback functions. Refer to \ref LoRaMacCallback_t.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks );
+
+/*!
+ * \brief Queries the LoRaMAC if it is possible to send the next frame with
+ * a given payload size. The LoRaMAC takes scheduled MAC commands into
+ * account and reports, when the frame can be send or not.
+ *
+ * \param [IN] size - Size of applicative payload to be send next
+ *
+ * \param [OUT] txInfo - The structure \ref LoRaMacTxInfo_t contains
+ * information about the actual maximum payload possible
+ * ( according to the configured datarate or the next
+ * datarate according to ADR ), and the maximum frame
+ * size, taking the scheduled MAC commands into account.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. When the parameters are
+ * not valid, the function returns \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ * In case of a length error caused by the applicative payload size, the
+ * function returns LORAMAC_STATUS_LENGTH_ERROR. In case of a length error
+ * due to additional MAC commands in the queue, the function returns
+ * LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR. In case the query is valid, and
+ * the LoRaMAC is able to send the frame, the function returns LORAMAC_STATUS_OK. *
+ */
+LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo );
+
+/*!
+ * \brief LoRaMAC channel add service
+ *
+ * \details Adds a new channel to the channel list and activates the id in
+ * the channel mask. For the US915 band, all channels are enabled
+ * by default. It is not possible to activate less than 6 125 kHz
+ * channels.
+ *
+ * \param [IN] id - Id of the channel. Possible values are:
+ *
+ * 0-15 for EU868
+ * 0-72 for US915
+ *
+ * \param [IN] params - Channel parameters to set.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacChannelAdd( uint8_t id, ChannelParams_t params );
+
+/*!
+ * \brief LoRaMAC channel remove service
+ *
+ * \details Deactivates the id in the channel mask.
+ *
+ * \param [IN] id - Id of the channel.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacChannelRemove( uint8_t id );
+
+/*!
+ * \brief LoRaMAC multicast channel link service
+ *
+ * \details Links a multicast channel into the linked list.
+ *
+ * \param [IN] channelParam - Multicast channel parameters to link.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacMulticastChannelLink( MulticastParams_t *channelParam );
+
+/*!
+ * \brief LoRaMAC multicast channel unlink service
+ *
+ * \details Unlinks a multicast channel from the linked list.
+ *
+ * \param [IN] channelParam - Multicast channel parameters to unlink.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacMulticastChannelUnlink( MulticastParams_t *channelParam );
+
+/*!
+ * \brief LoRaMAC MIB-Get
+ *
+ * \details The mac information base service to get attributes of the LoRaMac
+ * layer.
+ *
+ * The following code-snippet shows how to use the API to get the
+ * parameter AdrEnable, defined by the enumeration type
+ * \ref MIB_ADR.
+ * \code
+ * MibRequestConfirm_t mibReq;
+ * mibReq.Type = MIB_ADR;
+ *
+ * if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK )
+ * {
+ * // LoRaMAC updated the parameter mibParam.AdrEnable
+ * }
+ * \endcode
+ *
+ * \param [IN] mibRequest - MIB-GET-Request to perform. Refer to \ref MibRequestConfirm_t.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacMibGetRequestConfirm( MibRequestConfirm_t *mibGet );
+
+/*!
+ * \brief LoRaMAC MIB-Set
+ *
+ * \details The mac information base service to set attributes of the LoRaMac
+ * layer.
+ *
+ * The following code-snippet shows how to use the API to set the
+ * parameter AdrEnable, defined by the enumeration type
+ * \ref MIB_ADR.
+ *
+ * \code
+ * MibRequestConfirm_t mibReq;
+ * mibReq.Type = MIB_ADR;
+ * mibReq.Param.AdrEnable = true;
+ *
+ * if( LoRaMacMibGetRequestConfirm( &mibReq ) == LORAMAC_STATUS_OK )
+ * {
+ * // LoRaMAC updated the parameter
+ * }
+ * \endcode
+ *
+ * \param [IN] mibRequest - MIB-SET-Request to perform. Refer to \ref MibRequestConfirm_t.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID.
+ */
+LoRaMacStatus_t LoRaMacMibSetRequestConfirm( MibRequestConfirm_t *mibSet );
+
+/*!
+ * \brief LoRaMAC MLME-Request
+ *
+ * \details The Mac layer management entity handles management services. The
+ * following code-snippet shows how to use the API to perform a
+ * network join request.
+ *
+ * \code
+ * static uint8_t DevEui[] =
+ * {
+ * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ * };
+ * static uint8_t AppEui[] =
+ * {
+ * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ * };
+ * static uint8_t AppKey[] =
+ * {
+ * 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ * 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C
+ * };
+ *
+ * MlmeReq_t mlmeReq;
+ * mlmeReq.Type = MLME_JOIN;
+ * mlmeReq.Req.Join.DevEui = DevEui;
+ * mlmeReq.Req.Join.AppEui = AppEui;
+ * mlmeReq.Req.Join.AppKey = AppKey;
+ *
+ * if( LoRaMacMlmeRequest( &mlmeReq ) == LORAMAC_STATUS_OK )
+ * {
+ * // Service started successfully. Waiting for the Mlme-Confirm event
+ * }
+ * \endcode
+ *
+ * \param [IN] mlmeRequest - MLME-Request to perform. Refer to \ref MlmeReq_t.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID,
+ * \ref LORAMAC_STATUS_NO_NETWORK_JOINED,
+ * \ref LORAMAC_STATUS_LENGTH_ERROR,
+ * \ref LORAMAC_STATUS_DEVICE_OFF.
+ */
+LoRaMacStatus_t LoRaMacMlmeRequest( MlmeReq_t *mlmeRequest );
+
+/*!
+ * \brief LoRaMAC MCPS-Request
+ *
+ * \details The Mac Common Part Sublayer handles data services. The following
+ * code-snippet shows how to use the API to send an unconfirmed
+ * LoRaMAC frame.
+ *
+ * \code
+ * uint8_t myBuffer[] = { 1, 2, 3 };
+ *
+ * McpsReq_t mcpsReq;
+ * mcpsReq.Type = MCPS_UNCONFIRMED;
+ * mcpsReq.Req.Unconfirmed.fPort = 1;
+ * mcpsReq.Req.Unconfirmed.fBuffer = myBuffer;
+ * mcpsReq.Req.Unconfirmed.fBufferSize = sizeof( myBuffer );
+ *
+ * if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK )
+ * {
+ * // Service started successfully. Waiting for the MCPS-Confirm event
+ * }
+ * \endcode
+ *
+ * \param [IN] mcpsRequest - MCPS-Request to perform. Refer to \ref McpsReq_t.
+ *
+ * \retval LoRaMacStatus_t Status of the operation. Possible returns are:
+ * \ref LORAMAC_STATUS_OK,
+ * \ref LORAMAC_STATUS_BUSY,
+ * \ref LORAMAC_STATUS_SERVICE_UNKNOWN,
+ * \ref LORAMAC_STATUS_PARAMETER_INVALID,
+ * \ref LORAMAC_STATUS_NO_NETWORK_JOINED,
+ * \ref LORAMAC_STATUS_LENGTH_ERROR,
+ * \ref LORAMAC_STATUS_DEVICE_OFF.
+ */
+LoRaMacStatus_t LoRaMacMcpsRequest( McpsReq_t *mcpsRequest );
+
+/*!
+ * \brief Get LoRaMAC Join Request Retransmission Backoff time
+ *
+ * \retval Retransmission backoff time remaining until next
+ * join request can be sent
+ */
+ TimerTime_t LoRaMacCalcJoinBackOff( );
+
+/*!
+ * \brief LoRaMacGetMaxAppPayloadLength
+ *
+ * \retval The maximum application payload length based on the current datarate
+ * and repeater support
+ *
+ */
+uint8_t LoRaMacGetMaxAppPayloadLength();
+
+
+/*! \} defgroup LORAMAC */
+
+#endif // __LORAMAC_H__
