[wpilib] Add LED pattern API for easily animating addressable LEDs (#6344)

Add LEDReader and LEDWriter helper interfaces to facilitate composing simple patterns into more complex ones, e.g. LEDPattern.solid(Color.kBlue).breathe(Seconds.of(0.75)). Pattern composition relies on changing out the write behavior; for example, offsetBy increments the indexes to write to; while blink will switch between playing a base pattern and turning off all the LEDs.

Add a view class for splitting a single large buffer into smaller distinct sections, which is useful for dealing with long chained LED strips mounted on different parts of a robot. Views cannot be written directly to an LED strip (in fact, trying to do so won't even compile).

Adds some utility methods to the Color class for interpolating between two colors, and support color representations with 32-bit integers to avoid object allocations.

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
This commit is contained in:
Sam Carlberg
2024-06-05 22:41:10 -04:00
committed by GitHub
parent 5221069bcc
commit ad18fa62ee
19 changed files with 3610 additions and 311 deletions

View File

@@ -169,4 +169,41 @@ constexpr units::radian_t AngleModulus(units::radian_t angle) {
units::radian_t{std::numbers::pi});
}
// floorDiv and floorMod algorithms taken from Java
/**
* Returns the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
*/
constexpr std::signed_integral auto FloorDiv(std::signed_integral auto x,
std::signed_integral auto y) {
auto quot = x / y;
auto rem = x % y;
// if the signs are different and modulo not zero, round down
if ((x < 0) != (y < 0) && rem != 0) {
--quot;
}
return quot;
}
/**
* Returns the floor modulus of the {@code int} arguments.
* <p>
* The floor modulus is {@code r = x - (floorDiv(x, y) * y)},
* has the same sign as the divisor {@code y} or is zero, and
* is in the range of {@code -std::abs(y) < r < +std::abs(y)}.
*
* @param x the dividend
* @param y the divisor
* @return the floor modulus {@code x - (floorDiv(x, y) * y)}
*/
constexpr std::signed_integral auto FloorMod(std::signed_integral auto x,
std::signed_integral auto y) {
return x - FloorDiv(x, y) * y;
}
} // namespace frc