8484 */
8585#define BACKOFF_DC_24_HOURS 10000
8686
87+ /*!
88+ * Maximum value for the ADR ack counter
89+ */
90+ #define ADR_ACK_COUNTER_MAX 0xFFFFFFFF
91+
8792/*!
8893 * LoRaMac internal states
8994 */
@@ -664,6 +669,16 @@ static bool CheckRetransUnconfirmedUplink( void );
664669 */
665670static bool CheckRetransConfirmedUplink ( void );
666671
672+ /*!
673+ * \brief Increases the ADR ack counter. Takes the maximum
674+ * value into account.
675+ *
676+ * \param [IN] counter Current counter value.
677+ *
678+ * \retval Returns the next counter value.
679+ */
680+ static uint32_t IncreaseAdrAckCounter ( uint32_t counter );
681+
667682/*!
668683 * \brief Stops the uplink retransmission
669684 *
@@ -1971,38 +1986,79 @@ static void ProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8_t comm
19711986 uint8_t linkAdrNbRep = 0 ;
19721987 uint8_t linkAdrNbBytesParsed = 0 ;
19731988
1989+ // The end node is allowed to process one block of LinkAdrRequests.
1990+ // It must ignore subsequent blocks
19741991 if ( adrBlockFound == false )
19751992 {
19761993 adrBlockFound = true;
19771994
1978- // Fill parameter structure
1979- linkAdrReq .Payload = & payload [macIndex - 1 ];
1980- linkAdrReq .PayloadSize = commandsSize - ( macIndex - 1 );
1981- linkAdrReq .AdrEnabled = MacCtx .NvmCtx -> AdrCtrlOn ;
1982- linkAdrReq .UplinkDwellTime = MacCtx .NvmCtx -> MacParams .UplinkDwellTime ;
1983- linkAdrReq .CurrentDatarate = MacCtx .NvmCtx -> MacParams .ChannelsDatarate ;
1984- linkAdrReq .CurrentTxPower = MacCtx .NvmCtx -> MacParams .ChannelsTxPower ;
1985- linkAdrReq .CurrentNbRep = MacCtx .NvmCtx -> MacParams .ChannelsNbTrans ;
1986- linkAdrReq .Version = MacCtx .NvmCtx -> Version ;
1987-
1988- // Process the ADR requests
1989- status = RegionLinkAdrReq ( MacCtx .NvmCtx -> Region , & linkAdrReq , & linkAdrDatarate ,
1990- & linkAdrTxPower , & linkAdrNbRep , & linkAdrNbBytesParsed );
1991-
1992- if ( ( status & 0x07 ) == 0x07 )
1995+ do
19931996 {
1994- MacCtx .NvmCtx -> MacParams .ChannelsDatarate = linkAdrDatarate ;
1995- MacCtx .NvmCtx -> MacParams .ChannelsTxPower = linkAdrTxPower ;
1996- MacCtx .NvmCtx -> MacParams .ChannelsNbTrans = linkAdrNbRep ;
1997- }
1998-
1999- // Add the answers to the buffer
2000- for ( uint8_t i = 0 ; i < ( linkAdrNbBytesParsed / 5 ); i ++ )
1997+ // Fill parameter structure
1998+ linkAdrReq .Payload = & payload [macIndex - 1 ];
1999+ linkAdrReq .AdrEnabled = MacCtx .NvmCtx -> AdrCtrlOn ;
2000+ linkAdrReq .UplinkDwellTime = MacCtx .NvmCtx -> MacParams .UplinkDwellTime ;
2001+ linkAdrReq .CurrentDatarate = MacCtx .NvmCtx -> MacParams .ChannelsDatarate ;
2002+ linkAdrReq .CurrentTxPower = MacCtx .NvmCtx -> MacParams .ChannelsTxPower ;
2003+ linkAdrReq .CurrentNbRep = MacCtx .NvmCtx -> MacParams .ChannelsNbTrans ;
2004+ linkAdrReq .Version = MacCtx .NvmCtx -> Version ;
2005+
2006+ // There is a fundamental difference in reporting the status
2007+ // of the LinkAdrRequests when ADR is on or off. When ADR is on, every
2008+ // LinkAdrAns contains the same value. This does not hold when ADR is off,
2009+ // where every LinkAdrAns requires an individual status.
2010+ if ( MacCtx .NvmCtx -> AdrCtrlOn == true )
2011+ {
2012+ // When ADR is on, the function RegionLinkAdrReq will take care
2013+ // about the parsing and interpretation of the LinkAdrRequest block and
2014+ // it provides one status which shall be applied to every LinkAdrAns
2015+ linkAdrReq .PayloadSize = commandsSize - ( macIndex - 1 );
2016+ }
2017+ else
2018+ {
2019+ // When ADR is off, this function will loop over the individual LinkAdrRequests
2020+ // and will call RegionLinkAdrReq for each individually, as every request
2021+ // requires an individual answer.
2022+ // When ADR is off, the function RegionLinkAdrReq ignores the new values for
2023+ // ChannelsDatarate, ChannelsTxPower and ChannelsNbTrans.
2024+ linkAdrReq .PayloadSize = 5 ;
2025+ }
2026+
2027+ // Process the ADR requests
2028+ status = RegionLinkAdrReq ( MacCtx .NvmCtx -> Region , & linkAdrReq , & linkAdrDatarate ,
2029+ & linkAdrTxPower , & linkAdrNbRep , & linkAdrNbBytesParsed );
2030+
2031+ if ( ( status & 0x07 ) == 0x07 )
2032+ {
2033+ MacCtx .NvmCtx -> MacParams .ChannelsDatarate = linkAdrDatarate ;
2034+ MacCtx .NvmCtx -> MacParams .ChannelsTxPower = linkAdrTxPower ;
2035+ MacCtx .NvmCtx -> MacParams .ChannelsNbTrans = linkAdrNbRep ;
2036+ }
2037+
2038+ // Add the answers to the buffer
2039+ for ( uint8_t i = 0 ; i < ( linkAdrNbBytesParsed / 5 ); i ++ )
2040+ {
2041+ LoRaMacCommandsAddCmd ( MOTE_MAC_LINK_ADR_ANS , & status , 1 );
2042+ }
2043+ // Update MAC index
2044+ macIndex += linkAdrNbBytesParsed - 1 ;
2045+
2046+ // Check to prevent invalid access
2047+ if ( macIndex >= commandsSize )
2048+ break ;
2049+
2050+ } while ( payload [macIndex ++ ] == SRV_MAC_LINK_ADR_REQ );
2051+
2052+ if ( macIndex < commandsSize )
20012053 {
2002- LoRaMacCommandsAddCmd ( MOTE_MAC_LINK_ADR_ANS , & status , 1 );
2054+ // Decrease the index such that it points to the next MAC command
2055+ macIndex -- ;
20032056 }
2004- // Update MAC index
2005- macIndex += linkAdrNbBytesParsed - 1 ;
2057+ }
2058+ else
2059+ {
2060+ // Increase the index by the MAC command size (without command)
2061+ macIndex += 4 ;
20062062 }
20072063 break ;
20082064 }
@@ -2298,19 +2354,20 @@ LoRaMacStatus_t Send( LoRaMacHeader_t* macHdr, uint8_t fPort, void* fBuffer, uin
22982354 }
22992355
23002356 // ADR next request
2301- adrNext .Version = MacCtx .NvmCtx -> Version ;
23022357 adrNext .UpdateChanMask = true;
23032358 adrNext .AdrEnabled = fCtrl .Bits .Adr ;
23042359 adrNext .AdrAckCounter = MacCtx .NvmCtx -> AdrAckCounter ;
23052360 adrNext .AdrAckLimit = MacCtx .AdrAckLimit ;
23062361 adrNext .AdrAckDelay = MacCtx .AdrAckDelay ;
23072362 adrNext .Datarate = MacCtx .NvmCtx -> MacParams .ChannelsDatarate ;
23082363 adrNext .TxPower = MacCtx .NvmCtx -> MacParams .ChannelsTxPower ;
2364+ adrNext .NbTrans = MacCtx .ChannelsNbTransCounter ;
23092365 adrNext .UplinkDwellTime = MacCtx .NvmCtx -> MacParams .UplinkDwellTime ;
23102366 adrNext .Region = MacCtx .NvmCtx -> Region ;
23112367
23122368 fCtrl .Bits .AdrAckReq = LoRaMacAdrCalcNext ( & adrNext , & MacCtx .NvmCtx -> MacParams .ChannelsDatarate ,
2313- & MacCtx .NvmCtx -> MacParams .ChannelsTxPower , & adrAckCounter );
2369+ & MacCtx .NvmCtx -> MacParams .ChannelsTxPower ,
2370+ & MacCtx .ChannelsNbTransCounter , & adrAckCounter );
23142371
23152372 // Prepare the frame
23162373 status = PrepareFrame ( macHdr , & fCtrl , fPort , fBuffer , fBufferSize );
@@ -3087,6 +3144,15 @@ static bool CheckRetransConfirmedUplink( void )
30873144 return false;
30883145}
30893146
3147+ static uint32_t IncreaseAdrAckCounter ( uint32_t counter )
3148+ {
3149+ if ( counter < ADR_ACK_COUNTER_MAX )
3150+ {
3151+ counter ++ ;
3152+ }
3153+ return counter ;
3154+ }
3155+
30903156static bool StopRetransmission ( void )
30913157{
30923158 if ( ( MacCtx .MacFlags .Bits .McpsInd == 0 ) ||
@@ -3442,6 +3508,7 @@ LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
34423508 uint32_t adrAckCounter = MacCtx .NvmCtx -> AdrAckCounter ;
34433509 int8_t datarate = MacCtx .NvmCtx -> MacParamsDefaults .ChannelsDatarate ;
34443510 int8_t txPower = MacCtx .NvmCtx -> MacParamsDefaults .ChannelsTxPower ;
3511+ uint8_t nbTrans = MacCtx .ChannelsNbTransCounter ;
34453512 size_t macCmdsSize = 0 ;
34463513
34473514 if ( txInfo == NULL )
@@ -3450,20 +3517,20 @@ LoRaMacStatus_t LoRaMacQueryTxPossible( uint8_t size, LoRaMacTxInfo_t* txInfo )
34503517 }
34513518
34523519 // Setup ADR request
3453- adrNext .Version = MacCtx .NvmCtx -> Version ;
34543520 adrNext .UpdateChanMask = false;
34553521 adrNext .AdrEnabled = MacCtx .NvmCtx -> AdrCtrlOn ;
34563522 adrNext .AdrAckCounter = MacCtx .NvmCtx -> AdrAckCounter ;
34573523 adrNext .AdrAckLimit = MacCtx .AdrAckLimit ;
34583524 adrNext .AdrAckDelay = MacCtx .AdrAckDelay ;
34593525 adrNext .Datarate = MacCtx .NvmCtx -> MacParams .ChannelsDatarate ;
34603526 adrNext .TxPower = MacCtx .NvmCtx -> MacParams .ChannelsTxPower ;
3527+ adrNext .NbTrans = MacCtx .ChannelsNbTransCounter ;
34613528 adrNext .UplinkDwellTime = MacCtx .NvmCtx -> MacParams .UplinkDwellTime ;
34623529 adrNext .Region = MacCtx .NvmCtx -> Region ;
34633530
34643531 // We call the function for information purposes only. We don't want to
34653532 // apply the datarate, the tx power and the ADR ack counter.
3466- LoRaMacAdrCalcNext ( & adrNext , & datarate , & txPower , & adrAckCounter );
3533+ LoRaMacAdrCalcNext ( & adrNext , & datarate , & txPower , & nbTrans , & adrAckCounter );
34673534
34683535 txInfo -> CurrentPossiblePayloadSize = GetMaxAppPayloadWithoutFOptsLength ( datarate );
34693536
0 commit comments