3333#include "utilities.h"
3434#include "RegionCommon.h"
3535
36- #define BACKOFF_DC_1_HOUR 100
37- #define BACKOFF_DC_10_HOURS 1000
38- #define BACKOFF_DC_24_HOURS 10000
36+ #define BACKOFF_DC_1_HOUR 100
37+ #define BACKOFF_DC_10_HOURS 1000
38+ #define BACKOFF_DC_24_HOURS 10000
39+ #define BACKOFF_DC_TIMER_PERIOD_FACTOR 100
3940
40- static uint16_t SetMaxTimeCredits ( Band_t * band , bool joined , SysTime_t elapsedTime )
41+ #ifndef DUTY_CYCLE_TIME_PERIOD
42+ /*!
43+ * Default duty cycle time period is 1 hour = 3600000 ms
44+ */
45+ #define DUTY_CYCLE_TIME_PERIOD 3600000
46+ #endif
47+
48+ static uint16_t GetDutyCycle ( Band_t * band , bool joined , SysTime_t elapsedTimeSinceStartup )
4149{
42- uint16_t joinDutyCycle = RegionCommonGetJoinDc ( elapsedTime );
50+ uint16_t joinDutyCycle = RegionCommonGetJoinDc ( elapsedTimeSinceStartup );
4351 uint16_t dutyCycle = band -> DCycle ;
4452
4553 if ( joined == false )
4654 {
4755 // Get the join duty cycle which depends on the runtime
48- joinDutyCycle = RegionCommonGetJoinDc ( elapsedTime );
56+ joinDutyCycle = RegionCommonGetJoinDc ( elapsedTimeSinceStartup );
4957 // Take the most restrictive duty cycle
5058 dutyCycle = MAX ( dutyCycle , joinDutyCycle );
5159 }
@@ -56,14 +64,32 @@ static uint16_t SetMaxTimeCredits( Band_t* band, bool joined, SysTime_t elapsedT
5664 dutyCycle = 1 ;
5765 }
5866
67+ return dutyCycle ;
68+ }
69+
70+ static uint16_t SetMaxTimeCredits ( Band_t * band , bool joined , SysTime_t elapsedTimeSinceStartup )
71+ {
72+ uint16_t dutyCycle = band -> DCycle ;
73+ uint8_t timePeriodFactor = 1 ;
74+
75+ // Get the band duty cycle. If not joined, the function either returns the join duty cycle
76+ // or the band duty cycle, whichever is more restrictive.
77+ dutyCycle = GetDutyCycle ( band , joined , elapsedTimeSinceStartup );
78+
79+ if ( joined == false )
80+ {
81+ // Apply a factor to increase the maximum time period of observation
82+ timePeriodFactor = dutyCycle / BACKOFF_DC_TIMER_PERIOD_FACTOR ;
83+ }
84+
5985 // Setup the maximum allowed credits
60- band -> MaxTimeCredits = DUTY_CYCLE_TIME_PERIOD / dutyCycle ;
86+ band -> MaxTimeCredits = DUTY_CYCLE_TIME_PERIOD * timePeriodFactor ;
6187
6288 // In case if it is the first time, update also the current
6389 // time credits
6490 if ( band -> LastBandUpdateTime == 0 )
6591 {
66- band -> TimeCredits = DUTY_CYCLE_TIME_PERIOD / dutyCycle ;
92+ band -> TimeCredits = band -> MaxTimeCredits ;
6793 }
6894
6995 return dutyCycle ;
@@ -96,7 +122,7 @@ static uint16_t UpdateTimeCredits( Band_t* band, bool joined, bool dutyCycleEnab
96122 }
97123
98124 // Get the difference between now and the last update
99- band -> TimeCredits += ( TimerGetElapsedTime ( band -> LastBandUpdateTime ) / dutyCycle );
125+ band -> TimeCredits += TimerGetElapsedTime ( band -> LastBandUpdateTime );
100126
101127 // Limit band credits to maximum
102128 if ( band -> TimeCredits > band -> MaxTimeCredits )
@@ -220,13 +246,17 @@ void RegionCommonChanMaskCopy( uint16_t* channelsMaskDest, uint16_t* channelsMas
220246 }
221247}
222248
223- void RegionCommonSetBandTxDone ( Band_t * band , TimerTime_t lastTxAirTime )
249+ void RegionCommonSetBandTxDone ( Band_t * band , TimerTime_t lastTxAirTime , bool joined , SysTime_t elapsedTimeSinceStartup )
224250{
251+ // Get the band duty cycle. If not joined, the function either returns the join duty cycle
252+ // or the band duty cycle, whichever is more restrictive.
253+ uint16_t dutyCycle = GetDutyCycle ( band , joined , elapsedTimeSinceStartup );
254+
225255 // Reduce with transmission time
226- if ( band -> TimeCredits > lastTxAirTime )
256+ if ( band -> TimeCredits > ( lastTxAirTime * dutyCycle ) )
227257 {
228258 // Reduce time credits by the time of air
229- band -> TimeCredits -= lastTxAirTime ;
259+ band -> TimeCredits -= ( lastTxAirTime * dutyCycle ) ;
230260 }
231261 else
232262 {
@@ -239,56 +269,64 @@ TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
239269 bool lastTxIsJoinRequest , SysTime_t elapsedTimeSinceStartup ,
240270 TimerTime_t expectedTimeOnAir )
241271{
242- TimerTime_t maxCredits = 0 ;
272+ TimerTime_t minTimeToWait = TIMERTIME_T_MAX ;
243273 TimerTime_t currentTime = TimerGetCurrentTime ( );
274+ TimerTime_t creditCosts = 0 ;
244275 uint16_t dutyCycle = 1 ;
245- uint16_t maxDutyCycle = 0 ;
276+ uint8_t validBands = 0 ;
246277
247- // Update bands
248278 for ( uint8_t i = 0 ; i < nbBands ; i ++ )
249279 {
250- // Synchronization
280+ // Synchronization of bands and credits
251281 dutyCycle = UpdateTimeCredits ( & bands [i ], joined , dutyCycleEnabled ,
252282 lastTxIsJoinRequest , elapsedTimeSinceStartup ,
253283 currentTime );
254284
285+ // Calculate the credit costs for the next transmission
286+ // with the duty cycle and the expected time on air
287+ creditCosts = expectedTimeOnAir * dutyCycle ;
288+
255289 // Check if the band is ready for transmission. Its ready,
256290 // when the duty cycle is off, or the TimeCredits of the band
257- // is higher than the expected time on air .
258- if ( ( bands [i ].TimeCredits > expectedTimeOnAir ) ||
291+ // is higher than the credit costs for the transmission .
292+ if ( ( bands [i ].TimeCredits > creditCosts ) ||
259293 ( dutyCycleEnabled == false ) )
260294 {
261295 bands [i ].ReadyForTransmission = true;
296+ // This band is a potential candidate for an
297+ // upcoming transmission, so increase the counter.
298+ validBands ++ ;
262299 }
263300 else
264301 {
302+ // In this case, the band has not enough credits
303+ // for the next transmission.
265304 bands [i ].ReadyForTransmission = false;
266- }
267305
268- // Get the band with the maximum credits
269- if ( ( maxCredits < bands [i ].TimeCredits ) &&
270- ( bands [i ].TimeCredits != bands [i ].MaxTimeCredits ) )
271- {
272- maxCredits = bands [i ].TimeCredits ;
273- maxDutyCycle = dutyCycle ;
306+ if ( bands [i ].MaxTimeCredits > creditCosts )
307+ {
308+ // The band can only be taken into account, if the maximum credits
309+ // of the band are higher than the credit costs.
310+ // We calculate the minTimeToWait among the bands which are not
311+ // ready for transmission and which are potentially available
312+ // for a transmission in the future.
313+ minTimeToWait = MIN ( minTimeToWait , ( creditCosts - bands [i ].TimeCredits ) );
314+ // This band is a potential candidate for an
315+ // upcoming transmission (even if its time credits are not enough
316+ // at the moment), so increase the counter.
317+ validBands ++ ;
318+ }
274319 }
275320 }
276321
277- // Calculate the difference to the expected time on air, if the
278- // expected time on air is greater than the credits of the band with highest
279- // time credit value
280- if ( maxCredits < expectedTimeOnAir )
281- {
282- maxCredits = expectedTimeOnAir - maxCredits ;
283- }
284- else
322+
323+ if ( validBands == 0 )
285324 {
286- maxCredits = 0 ;
325+ // There is no valid band available to handle a transmission
326+ // in the given DUTY_CYCLE_TIME_PERIOD.
327+ return TIMERTIME_T_MAX ;
287328 }
288-
289- // Calculate the return value which shall be
290- // the waiting time for the next transmission
291- return maxCredits * maxDutyCycle ;
329+ return minTimeToWait ;
292330}
293331
294332uint8_t RegionCommonParseLinkAdrReq ( uint8_t * payload , RegionCommonLinkAdrParams_t * linkAdrParams )
@@ -490,7 +528,7 @@ LoRaMacStatus_t RegionCommonIdentifyChannels( RegionCommonIdentifyChannelsParam_
490528 identifyChannelsParam -> MaxBands ,
491529 identifyChannelsParam -> DutyCycleEnabled ,
492530 identifyChannelsParam -> LastTxIsJoinRequest ,
493- identifyChannelsParam -> ElapsedTime ,
531+ identifyChannelsParam -> ElapsedTimeSinceStartUp ,
494532 identifyChannelsParam -> ExpectedTimeOnAir );
495533
496534 RegionCommonCountNbOfEnabledChannels ( identifyChannelsParam -> CountNbOfEnabledChannelsParam , enabledChannels ,
0 commit comments