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; }