Fork of Semtech LoRaWAN stack
Fork of LoRaWAN-lib by
Diff: LoRaMac.cpp
- Branch:
- v4.2.0
- Revision:
- 27:cda377b2a41f
- Parent:
- 26:4627985dc5be
- Child:
- 29:c7583fcfad8c
--- a/LoRaMac.cpp Wed Nov 09 06:05:41 2016 +0000
+++ b/LoRaMac.cpp Fri Nov 11 16:03:36 2016 -0500
@@ -197,10 +197,20 @@
static uint8_t MacCommandsBufferIndex = 0;
/*!
+ * Contains the current MacCommandsBuffer index for MAC commands to repeat
+ */
+static uint8_t MacCommandsBufferToRepeatIndex = 0;
+
+/*!
* Buffer containing the MAC layer commands
*/
static uint8_t MacCommandsBuffer[LORA_MAC_COMMAND_MAX_LENGTH];
+/*!
+ * Buffer containing the MAC layer commands which must be repeated
+ */
+static uint8_t MacCommandsBufferToRepeat[LORA_MAC_COMMAND_MAX_LENGTH];
+
#if defined( USE_BAND_433 )
/*!
* Data rates table definition
@@ -755,6 +765,20 @@
static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 );
/*!
+ * \brief Parses the MAC commands which must be repeated.
+ *
+ * \Remark MAC layer internal function
+ *
+ * \param [IN] cmdBufIn Buffer which stores the MAC commands to send
+ * \param [IN] length Length of the input buffer to parse
+ * \param [OUT] cmdBufOut Buffer which stores the MAC commands which must be
+ * repeated.
+ *
+ * \retval Size of the MAC commands to repeat.
+ */
+static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut );
+
+/*!
* \brief Validates if the payload fits into the frame, taking the datarate
* into account.
*
@@ -1214,6 +1238,7 @@
McpsConfirm.Status = LORAMAC_EVENT_INFO_STATUS_OK;
AdrAckCounter = 0;
+ MacCommandsBufferToRepeatIndex = 0;
// Update 32 bits downlink counter
if( multicast == 1 )
@@ -2361,11 +2386,13 @@
static LoRaMacStatus_t AddMacCommand( uint8_t cmd, uint8_t p1, uint8_t p2 )
{
LoRaMacStatus_t status = LORAMAC_STATUS_BUSY;
+ // The maximum buffer length must take MAC commands to re-send into account.
+ uint8_t bufLen = LORA_MAC_COMMAND_MAX_LENGTH - MacCommandsBufferToRepeatIndex;
switch( cmd )
{
case MOTE_MAC_LINK_CHECK_REQ:
- if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ if( MacCommandsBufferIndex < bufLen )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this command
@@ -2373,7 +2400,7 @@
}
break;
case MOTE_MAC_LINK_ADR_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 1 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Margin
@@ -2382,7 +2409,7 @@
}
break;
case MOTE_MAC_DUTY_CYCLE_ANS:
- if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ if( MacCommandsBufferIndex < bufLen )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this answer
@@ -2390,7 +2417,7 @@
}
break;
case MOTE_MAC_RX_PARAM_SETUP_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 1 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Status: Datarate ACK, Channel ACK
@@ -2399,7 +2426,7 @@
}
break;
case MOTE_MAC_DEV_STATUS_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 2 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 2 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// 1st byte Battery
@@ -2410,7 +2437,7 @@
}
break;
case MOTE_MAC_NEW_CHANNEL_ANS:
- if( MacCommandsBufferIndex < ( LORA_MAC_COMMAND_MAX_LENGTH - 1 ) )
+ if( MacCommandsBufferIndex < ( bufLen - 1 ) )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// Status: Datarate range OK, Channel frequency OK
@@ -2419,7 +2446,7 @@
}
break;
case MOTE_MAC_RX_TIMING_SETUP_ANS:
- if( MacCommandsBufferIndex < LORA_MAC_COMMAND_MAX_LENGTH )
+ if( MacCommandsBufferIndex < bufLen )
{
MacCommandsBuffer[MacCommandsBufferIndex++] = cmd;
// No payload for this answer
@@ -2436,6 +2463,40 @@
return status;
}
+static uint8_t ParseMacCommandsToRepeat( uint8_t* cmdBufIn, uint8_t length, uint8_t* cmdBufOut )
+{
+ uint8_t i = 0;
+ uint8_t cmdCount = 0;
+
+ if( ( cmdBufIn == NULL ) || ( cmdBufOut == NULL ) )
+ {
+ return 0;
+ }
+
+ for( i = 0; i < length; i++ )
+ {
+ switch( cmdBufIn[i] )
+ {
+ case MOTE_MAC_RX_PARAM_SETUP_ANS:
+ {
+ cmdBufOut[cmdCount++] = cmdBufIn[i++];
+ cmdBufOut[cmdCount++] = cmdBufIn[i++];
+ cmdBufOut[cmdCount++] = cmdBufIn[i];
+ break;
+ }
+ case MOTE_MAC_RX_TIMING_SETUP_ANS:
+ {
+ cmdBufOut[cmdCount++] = cmdBufIn[i];
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return cmdCount;
+}
+
static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t commandsSize, uint8_t snr )
{
uint8_t validLinkAdrCmds = 0;
@@ -2991,6 +3052,10 @@
LoRaMacBuffer[pktHeaderLen++] = UpLinkCounter & 0xFF;
LoRaMacBuffer[pktHeaderLen++] = ( UpLinkCounter >> 8 ) & 0xFF;
+ // Copy the MAC commands which must be re-send into the MAC command buffer
+ memcpy1( &MacCommandsBuffer[MacCommandsBufferIndex], MacCommandsBufferToRepeat, MacCommandsBufferToRepeatIndex );
+ MacCommandsBufferIndex += MacCommandsBufferToRepeatIndex;
+
if( ( payload != NULL ) && ( payloadSize > 0 ) )
{
if( ( MacCommandsBufferIndex <= LORA_MAC_COMMAND_MAX_LENGTH ) && ( MacCommandsInNextTx == true ) )
@@ -3015,6 +3080,12 @@
}
}
MacCommandsInNextTx = false;
+ // Store MAC commands which must be re-send in case the device does not receive a downlink anymore
+ MacCommandsBufferToRepeatIndex = ParseMacCommandsToRepeat( MacCommandsBuffer, MacCommandsBufferIndex, MacCommandsBufferToRepeat );
+ if( MacCommandsBufferToRepeatIndex > 0 )
+ {
+ MacCommandsInNextTx = true;
+ }
MacCommandsBufferIndex = 0;
if( ( payload != NULL ) && ( payloadSize > 0 ) )
@@ -3125,6 +3196,7 @@
return LORAMAC_STATUS_OK;
}
+
LoRaMacStatus_t LoRaMacInitialization( LoRaMacPrimitives_t *primitives, LoRaMacCallback_t *callbacks )
{
if( primitives == NULL )
@@ -3150,11 +3222,29 @@
DownLinkCounter = 0;
AdrAckCounter = 0;
+ ChannelsNbRepCounter = 0;
+
+ AckTimeoutRetries = 1;
+ AckTimeoutRetriesCounter = 1;
+ AckTimeoutRetry = false;
+
+ MaxDCycle = 0;
+ AggregatedDCycle = 1;
+
+ MacCommandsBufferIndex = 0;
+ MacCommandsBufferToRepeatIndex = 0;
+
+ IsRxWindowsEnabled = true;
+
RepeaterSupport = false;
IsRxWindowsEnabled = true;
IsLoRaMacNetworkJoined = false;
LoRaMacState = MAC_IDLE;
+ NodeAckRequested = false;
+ SrvAckRequested = false;
+ MacCommandsInNextTx = false;
+
#if defined( USE_BAND_433 )
ChannelsMask[0] = LC( 1 ) + LC( 2 ) + LC( 3 );
#elif defined( USE_BAND_780 )
@@ -3274,7 +3364,8 @@
LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
{
- int8_t datarate = ChannelsDefaultDatarate;
+ int8_t datarate = ChannelsDefaultDatarate;
+ uint8_t fOptLen = MacCommandsBufferIndex + MacCommandsBufferToRepeatIndex;
if( txInfo == NULL )
{
@@ -3292,9 +3383,9 @@
txInfo->CurrentPayloadSize = MaxPayloadOfDatarate[datarate];
}
- if( txInfo->CurrentPayloadSize >= MacCommandsBufferIndex )
+ if( txInfo->CurrentPayloadSize >= fOptLen )
{
- txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - MacCommandsBufferIndex;
+ txInfo->MaxPossiblePayload = txInfo->CurrentPayloadSize - fOptLen;
}
else
{
@@ -3306,7 +3397,7 @@
return LORAMAC_STATUS_LENGTH_ERROR;
}
- if( ValidatePayloadLength( size, datarate, MacCommandsBufferIndex ) == false )
+ if( ValidatePayloadLength( size, datarate, fOptLen ) == false )
{
return LORAMAC_STATUS_MAC_CMD_LENGTH_ERROR;
}
