use micromath::F32Ext;
use smart_leds_trait::RGB8;
pub const fn rgb(r: u8, g: u8, b: u8) -> RGB8 {
RGB8 { r, g, b }
}
pub const BLACK: RGB8 = RGB8 { r: 0, g: 0, b: 0 };
pub const WHITE: RGB8 = RGB8 {
r: 255,
g: 255,
b: 255,
};
pub const RED: RGB8 = RGB8 { r: 255, g: 0, b: 0 };
pub const GREEN: RGB8 = RGB8 { r: 0, g: 255, b: 0 };
pub const BLUE: RGB8 = RGB8 { r: 0, g: 0, b: 255 };
pub const PURPLE: RGB8 = RGB8 {
r: 128,
g: 0,
b: 128,
};
pub const ORANGE: RGB8 = RGB8 {
r: 255,
g: 165,
b: 0,
};
pub(crate) fn color_wheel(pos: u8) -> RGB8 {
let pos = 255 - pos;
if pos < 85 {
RGB8 {
r: 255 - pos * 3,
g: 0,
b: pos * 3,
}
} else if pos < 170 {
let pos = pos - 85;
RGB8 {
r: 0,
g: pos * 3,
b: 255 - pos * 3,
}
} else {
let pos = pos - 170;
RGB8 {
r: pos * 3,
g: 255 - pos * 3,
b: 0,
}
}
}
pub(crate) fn sine8(pos: u8) -> u8 {
let angle = pos as f32 * core::f32::consts::TAU / 256.0;
(angle.sin() * 127.5 + 127.5) as u8
}
pub(crate) fn color_blend(c1: RGB8, c2: RGB8, blend: u8) -> RGB8 {
let b = blend as u16;
let ib = 255 - b;
RGB8 {
r: ((c1.r as u16 * ib + c2.r as u16 * b) / 255) as u8,
g: ((c1.g as u16 * ib + c2.g as u16 * b) / 255) as u8,
b: ((c1.b as u16 * ib + c2.b as u16 * b) / 255) as u8,
}
}
pub(crate) fn fade_out(pixels: &mut [RGB8], target: RGB8, rate: u8) {
for p in pixels.iter_mut() {
*p = color_blend(*p, target, rate);
}
}
pub(crate) fn next_rand(state: u32) -> u32 {
let seed = if state == 0 {
0xdead_beef_u64
} else {
state as u64 | (state as u64) << 32
};
fastrand::Rng::with_seed(seed).u32(..)
}
pub(crate) fn rand_wheel_index(current: u8, rng: u32) -> (u8, u32) {
let mut rng = rng;
loop {
rng = next_rand(rng);
let r = rng as u8;
let x = (current as i16 - r as i16).unsigned_abs() as u8;
let d = x.min(255u8.saturating_sub(x));
if d >= 42 {
return (r, rng);
}
}
}