You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I’ve noticed a potential issue in the implementation of the canShow function, particularly in the way it handles counter rollovers for the 32-bit micros() timer. While the current logic does attempt to handle rollover scenarios, resetting endTime to now when endTime > now may introduce an unintended delay of up to 300 microseconds, which could lead to timing inconsistencies in certain edge cases.
Steps to Reproduce:
Use the Adafruit_NeoPixel library in an environment where micros() counter rollover is a possibility (approximately every 70 minutes).
Allow a significant delay between show() calls, such that endTime and now end up on either side of the 32-bit counter rollover.
Call canShow(). Observe that endTime > now triggers a reset of endTime to now, which effectively restarts the 300-microsecond timer.
Observed Behavior:
When the counter rolls over and endTime > now, the following line in the canShow function resets endTime to now:
if (endTime > now) {
endTime = now;
}
This introduces an additional delay of up to 300 microseconds because the now - endTime difference is effectively reset to 0.
For example:
Before rollover:
endTime = 0xFFFFFFF0
now = 0x00000010
After rollover handling: endTime = now
The 300-microsecond interval starts over unnecessarily.
Expected Behavior:
The function should account for the rollover naturally by using proper time difference calculations with uint32_t, leveraging the fact that unsigned integer arithmetic can handle rollovers correctly.
Suggested Fix:
Instead of resetting endTime to now, modify the logic to calculate the time difference directly, even in rollover cases. Here's a proposed fix for the canShow function:
boolcanShow(void) {
uint32_t now = micros();
// Calculate the time difference, accounting for rolloveruint32_t delta = (now >= endTime) ? (now - endTime) : (UINT32_MAX - endTime + now + 1);
return delta >= 300L; // Check if the delay has been satisfied
}
Why This Works:
When now < endTime (rollover scenario), the difference is computed as:
This naturally handles rollover without resetting endTime.
It avoids introducing unintended delays caused by resetting endTime to now.
Impact:
This issue may not affect typical NeoPixel usage with frequent show() calls, but in scenarios where show() is invoked infrequently (e.g., longer than 70 minutes), this behavior could cause timing inconsistencies or unexpected stalls.
Thank you for maintaining this excellent library! Please let me know if you need further clarification or testing support.
The text was updated successfully, but these errors were encountered:
Description:
Hello Adafruit NeoPixel Team,
I’ve noticed a potential issue in the implementation of the
canShow
function, particularly in the way it handles counter rollovers for the 32-bitmicros()
timer. While the current logic does attempt to handle rollover scenarios, resettingendTime
tonow
whenendTime > now
may introduce an unintended delay of up to 300 microseconds, which could lead to timing inconsistencies in certain edge cases.Steps to Reproduce:
Adafruit_NeoPixel
library in an environment wheremicros()
counter rollover is a possibility (approximately every 70 minutes).show()
calls, such thatendTime
andnow
end up on either side of the 32-bit counter rollover.canShow()
. Observe thatendTime > now
triggers a reset ofendTime
tonow
, which effectively restarts the 300-microsecond timer.Observed Behavior:
When the counter rolls over and
endTime > now
, the following line in thecanShow
function resetsendTime
tonow
:if (endTime > now) { endTime = now; }
This introduces an additional delay of up to 300 microseconds because the
now - endTime
difference is effectively reset to0
.For example:
endTime = 0xFFFFFFF0
now = 0x00000010
endTime = now
Expected Behavior:
The function should account for the rollover naturally by using proper time difference calculations with
uint32_t
, leveraging the fact that unsigned integer arithmetic can handle rollovers correctly.Suggested Fix:
Instead of resetting
endTime
tonow
, modify the logic to calculate the time difference directly, even in rollover cases. Here's a proposed fix for thecanShow
function:Why This Works:
now < endTime
(rollover scenario), the difference is computed as:This naturally handles rollover without resetting
endTime
.endTime
tonow
.Impact:
This issue may not affect typical NeoPixel usage with frequent
show()
calls, but in scenarios whereshow()
is invoked infrequently (e.g., longer than 70 minutes), this behavior could cause timing inconsistencies or unexpected stalls.Thank you for maintaining this excellent library! Please let me know if you need further clarification or testing support.
The text was updated successfully, but these errors were encountered: