3535#include "systime.h"
3636
3737#define BACKOFF_DC_1_HOUR 100
38- #define BACKOFF_DC_10_HOURS 1000
39- #define BACKOFF_DC_24_HOURS 10000
4038
4139#define BACKOFF_DUTY_CYCLE_1_HOUR_IN_S 3600
4240#define BACKOFF_DUTY_CYCLE_10_HOURS_IN_S ( BACKOFF_DUTY_CYCLE_1_HOUR_IN_S + ( BACKOFF_DUTY_CYCLE_1_HOUR_IN_S * 10 ) )
4543
4644#ifndef DUTY_CYCLE_TIME_PERIOD
4745/*!
48- * Default duty cycle observation time period
49- *
50- * \remark The ETSI observation time period is 1 hour (3600000 ms) but, the implemented algorithm may violate the
51- * defined duty-cycle restrictions. In order to ensure that these restrictions never get violated we changed the
52- * default duty cycle observation time period to 1/2 hour (1800000 ms).
46+ * Default duty cycle observation time period is 1 hour (3600000 ms) according to ETSI.
5347 */
54- #define DUTY_CYCLE_TIME_PERIOD 1800000
48+ #define DUTY_CYCLE_TIME_PERIOD 3600000
49+ #endif
50+
51+ #ifndef DUTY_CYCLE_TIME_PERIOD_JOIN_BACKOFF_24H
52+ /*!
53+ * Time credits for the join backoff algorithm for the 24H period.
54+ */
55+ #define DUTY_CYCLE_TIME_PERIOD_JOIN_BACKOFF_24H 870000
5556#endif
5657
5758/*!
@@ -78,20 +79,8 @@ static uint16_t GetDutyCycle( Band_t* band, bool joined, SysTime_t elapsedTimeSi
7879
7980 if ( joined == false )
8081 {
81- uint16_t joinDutyCycle = BACKOFF_DC_24_HOURS ;
82+ uint16_t joinDutyCycle = BACKOFF_DC_1_HOUR ;
8283
83- if ( elapsedTimeSinceStartup .Seconds < BACKOFF_DUTY_CYCLE_1_HOUR_IN_S )
84- {
85- joinDutyCycle = BACKOFF_DC_1_HOUR ;
86- }
87- else if ( elapsedTimeSinceStartup .Seconds < BACKOFF_DUTY_CYCLE_10_HOURS_IN_S )
88- {
89- joinDutyCycle = BACKOFF_DC_10_HOURS ;
90- }
91- else
92- {
93- joinDutyCycle = BACKOFF_DC_24_HOURS ;
94- }
9584 // Take the most restrictive duty cycle
9685 dutyCycle = MAX ( dutyCycle , joinDutyCycle );
9786 }
@@ -110,48 +99,24 @@ static uint16_t SetMaxTimeCredits( Band_t* band, bool joined, SysTime_t elapsedT
11099{
111100 uint16_t dutyCycle = band -> DCycle ;
112101 TimerTime_t maxCredits = DUTY_CYCLE_TIME_PERIOD ;
113- TimerTime_t elapsedTime = SysTimeToMs ( elapsedTimeSinceStartup );
114- SysTime_t timeDiff = { 0 };
115102
116103 // Get the band duty cycle. If not joined, the function either returns the join duty cycle
117104 // or the band duty cycle, whichever is more restrictive.
118105 dutyCycle = GetDutyCycle ( band , joined , elapsedTimeSinceStartup );
119106
120107 if ( joined == false )
121108 {
122- if ( dutyCycle == BACKOFF_DC_1_HOUR )
109+ if ( elapsedTimeSinceStartup . Seconds < BACKOFF_DUTY_CYCLE_1_HOUR_IN_S )
123110 {
124111 maxCredits = DUTY_CYCLE_TIME_PERIOD ;
125- band -> LastMaxCreditAssignTime = elapsedTime ;
126112 }
127- else if ( dutyCycle == BACKOFF_DC_10_HOURS )
113+ else if ( elapsedTimeSinceStartup . Seconds < BACKOFF_DUTY_CYCLE_10_HOURS_IN_S )
128114 {
129- maxCredits = DUTY_CYCLE_TIME_PERIOD * 10 ;
130- band -> LastMaxCreditAssignTime = elapsedTime ;
115+ maxCredits = DUTY_CYCLE_TIME_PERIOD ;
131116 }
132117 else
133118 {
134- maxCredits = DUTY_CYCLE_TIME_PERIOD * 24 ;
135- }
136-
137- timeDiff = SysTimeSub ( elapsedTimeSinceStartup , SysTimeFromMs ( band -> LastMaxCreditAssignTime ) );
138-
139- // Verify if we have to assign the maximum credits in cases
140- // of the preconditions have changed.
141- if ( ( ( dutyCycleEnabled == false ) && ( lastTxIsJoinRequest == false ) ) ||
142- ( band -> MaxTimeCredits != maxCredits ) ||
143- ( timeDiff .Seconds >= BACKOFF_24_HOURS_IN_S ) )
144- {
145- band -> TimeCredits = maxCredits ;
146-
147- if ( elapsedTimeSinceStartup .Seconds >= BACKOFF_DUTY_CYCLE_24_HOURS_IN_S )
148- {
149- timeDiff .Seconds = ( elapsedTimeSinceStartup .Seconds - BACKOFF_DUTY_CYCLE_24_HOURS_IN_S ) / BACKOFF_24_HOURS_IN_S ;
150- timeDiff .Seconds *= BACKOFF_24_HOURS_IN_S ;
151- timeDiff .Seconds += BACKOFF_DUTY_CYCLE_24_HOURS_IN_S ;
152- timeDiff .SubSeconds = 0 ;
153- band -> LastMaxCreditAssignTime = SysTimeToMs ( timeDiff );
154- }
119+ maxCredits = DUTY_CYCLE_TIME_PERIOD_JOIN_BACKOFF_24H ;
155120 }
156121 }
157122 else
@@ -163,12 +128,6 @@ static uint16_t SetMaxTimeCredits( Band_t* band, bool joined, SysTime_t elapsedT
163128 }
164129 }
165130
166- // Assign the max credits if its the first time
167- if ( band -> LastBandUpdateTime == 0 )
168- {
169- band -> TimeCredits = maxCredits ;
170- }
171-
172131 // Setup the maximum allowed credits. We can assign them
173132 // safely all the time.
174133 band -> MaxTimeCredits = maxCredits ;
@@ -178,27 +137,37 @@ static uint16_t SetMaxTimeCredits( Band_t* band, bool joined, SysTime_t elapsedT
178137
179138static uint16_t UpdateTimeCredits ( Band_t * band , bool joined , bool dutyCycleEnabled ,
180139 bool lastTxIsJoinRequest , SysTime_t elapsedTimeSinceStartup ,
181- TimerTime_t currentTime )
140+ TimerTime_t currentTime , TimerTime_t lastBandUpdateTime )
182141{
183142 uint16_t dutyCycle = SetMaxTimeCredits ( band , joined , elapsedTimeSinceStartup ,
184143 dutyCycleEnabled , lastTxIsJoinRequest );
144+ TimerTime_t observation = DUTY_CYCLE_TIME_PERIOD ;
185145
186- if ( joined == true )
146+ if ( joined == false )
187147 {
188- // Apply a sliding window for the duty cycle with collection and speding
189- // credits.
190- band -> TimeCredits += TimerGetElapsedTime ( band -> LastBandUpdateTime );
148+ if ( elapsedTimeSinceStartup .Seconds < BACKOFF_DUTY_CYCLE_1_HOUR_IN_S )
149+ {
150+ observation = BACKOFF_DUTY_CYCLE_1_HOUR_IN_S * 1000 ;
151+ }
152+ else if ( elapsedTimeSinceStartup .Seconds < BACKOFF_DUTY_CYCLE_10_HOURS_IN_S )
153+ {
154+ observation = ( BACKOFF_DUTY_CYCLE_10_HOURS_IN_S * 1000 );
155+ }
156+ else
157+ {
158+ observation = ( BACKOFF_DUTY_CYCLE_24_HOURS_IN_S * 1000 );
159+ }
191160 }
192161
193- // Limit band credits to maximum
194- if ( band -> TimeCredits > band -> MaxTimeCredits )
162+ // Apply new credits only if the observation period has been elapsed.
163+ if ( ( observation <= lastBandUpdateTime ) ||
164+ ( band -> LastMaxCreditAssignTime != observation ) ||
165+ ( band -> LastBandUpdateTime == 0 ) )
195166 {
196167 band -> TimeCredits = band -> MaxTimeCredits ;
168+ band -> LastBandUpdateTime = currentTime ;
169+ band -> LastMaxCreditAssignTime = observation ;
197170 }
198-
199- // Synchronize update time
200- band -> LastBandUpdateTime = currentTime ;
201-
202171 return dutyCycle ;
203172}
204173
@@ -324,10 +293,12 @@ TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
324293
325294 for ( uint8_t i = 0 ; i < nbBands ; i ++ )
326295 {
296+ TimerTime_t elapsedTime = TimerGetElapsedTime ( bands [i ].LastBandUpdateTime );
297+
327298 // Synchronization of bands and credits
328299 dutyCycle = UpdateTimeCredits ( & bands [i ], joined , dutyCycleEnabled ,
329300 lastTxIsJoinRequest , elapsedTimeSinceStartup ,
330- currentTime );
301+ currentTime , elapsedTime );
331302
332303 // Calculate the credit costs for the next transmission
333304 // with the duty cycle and the expected time on air
@@ -336,7 +307,7 @@ TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
336307 // Check if the band is ready for transmission. Its ready,
337308 // when the duty cycle is off, or the TimeCredits of the band
338309 // is higher than the credit costs for the transmission.
339- if ( ( bands [i ].TimeCredits >= creditCosts ) ||
310+ if ( ( bands [i ].TimeCredits > creditCosts ) ||
340311 ( ( dutyCycleEnabled == false ) && ( joined == true ) ) )
341312 {
342313 bands [i ].ReadyForTransmission = true;
@@ -350,49 +321,24 @@ TimerTime_t RegionCommonUpdateBandTimeOff( bool joined, Band_t* bands,
350321 // for the next transmission.
351322 bands [i ].ReadyForTransmission = false;
352323
353- if ( bands [i ].MaxTimeCredits >= creditCosts )
324+ if ( bands [i ].MaxTimeCredits > creditCosts )
354325 {
355326 // The band can only be taken into account, if the maximum credits
356327 // of the band are higher than the credit costs.
357328 // We calculate the minTimeToWait among the bands which are not
358329 // ready for transmission and which are potentially available
359330 // for a transmission in the future.
360- minTimeToWait = MIN ( minTimeToWait , ( creditCosts - bands [i ].TimeCredits ) );
331+ TimerTime_t observationTimeDiff = 0 ;
332+ if ( bands [i ].LastMaxCreditAssignTime >= elapsedTime )
333+ {
334+ observationTimeDiff = bands [i ].LastMaxCreditAssignTime - elapsedTime ;
335+ }
336+ minTimeToWait = MIN ( minTimeToWait , observationTimeDiff );
361337 // This band is a potential candidate for an
362338 // upcoming transmission (even if its time credits are not enough
363339 // at the moment), so increase the counter.
364340 validBands ++ ;
365341 }
366-
367- // Apply a special calculation if the device is not joined.
368- if ( joined == false )
369- {
370- SysTime_t backoffTimeRange = {
371- .Seconds = 0 ,
372- .SubSeconds = 0 ,
373- };
374- // Get the backoff time range based on the duty cycle definition
375- if ( dutyCycle == BACKOFF_DC_1_HOUR )
376- {
377- backoffTimeRange .Seconds = BACKOFF_DUTY_CYCLE_1_HOUR_IN_S ;
378- }
379- else if ( dutyCycle == BACKOFF_DC_10_HOURS )
380- {
381- backoffTimeRange .Seconds = BACKOFF_DUTY_CYCLE_10_HOURS_IN_S ;
382- }
383- else
384- {
385- backoffTimeRange .Seconds = BACKOFF_DUTY_CYCLE_24_HOURS_IN_S ;
386- }
387- // Calculate the time to wait.
388- if ( elapsedTimeSinceStartup .Seconds > BACKOFF_DUTY_CYCLE_24_HOURS_IN_S )
389- {
390- backoffTimeRange .Seconds += BACKOFF_24_HOURS_IN_S * ( ( ( elapsedTimeSinceStartup .Seconds - BACKOFF_DUTY_CYCLE_24_HOURS_IN_S ) / BACKOFF_24_HOURS_IN_S ) + 1 );
391- }
392- // Calculate the time difference between now and the next range
393- backoffTimeRange = SysTimeSub ( backoffTimeRange , elapsedTimeSinceStartup );
394- minTimeToWait = SysTimeToMs ( backoffTimeRange );
395- }
396342 }
397343 }
398344
0 commit comments