use smart_leds_trait::RGB8;
use crate::segment::{EffectConfig, EffectState};
use crate::utils::{BLACK, WHITE, color_wheel, next_rand, rand_wheel_index};
pub fn color_wipe(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len();
let step = state.counter as usize % (len * 2);
if step < len {
pixels[step] = config.colors[0];
} else {
pixels[step - len] = config.colors[1];
}
state.counter = state.counter.wrapping_add(1);
}
pub fn color_wipe_random(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len();
let step = state.counter as usize % (len * 2);
if step == 0 {
let idx = (state.aux & 0xFF) as u8;
let rng = state.aux >> 8;
let (new_idx, new_rng) = rand_wheel_index(idx, rng);
state.aux = new_idx as u32 | (new_rng << 8);
}
let color = color_wheel((state.aux & 0xFF) as u8);
if step < len {
pixels[step] = color;
} else {
pixels[step - len] = color;
}
state.counter = state.counter.wrapping_add(1);
}
pub fn color_sweep_random(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len();
let step = state.counter as usize % (len * 2);
let forward = (state.counter / (len as u32 * 2)) % 2 == 0;
if step == 0 {
let idx = (state.aux & 0xFF) as u8;
let rng = state.aux >> 8;
let (new_idx, new_rng) = rand_wheel_index(idx, rng);
state.aux = new_idx as u32 | (new_rng << 8);
}
let color = color_wheel((state.aux & 0xFF) as u8);
let pos = if forward {
step.min(len - 1)
} else {
len - 1 - step.min(len - 1)
};
if step < len {
pixels[pos] = color;
} else {
let off_pos = if forward {
step - len
} else {
len - 1 - (step - len).min(len - 1)
};
if off_pos < len {
pixels[off_pos] = BLACK;
}
}
state.counter = state.counter.wrapping_add(1);
}
pub fn scan(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len();
let pos = state.counter as usize;
let going_forward = state.aux == 0;
for p in pixels.iter_mut() {
*p = config.colors[1];
}
if pos < len {
pixels[pos] = config.colors[0];
}
if going_forward {
state.counter += 1;
if state.counter as usize >= len - 1 {
state.aux = 1;
}
} else {
state.counter = state.counter.saturating_sub(1);
if state.counter == 0 {
state.aux = 0;
}
}
}
pub fn dual_scan(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len();
let pos = state.counter as usize;
let going_forward = state.aux == 0;
for p in pixels.iter_mut() {
*p = config.colors[1];
}
if pos < len {
pixels[pos] = config.colors[0];
pixels[len - 1 - pos] = config.colors[0];
}
if going_forward {
state.counter += 1;
if state.counter as usize >= len / 2 {
state.aux = 1;
}
} else {
state.counter = state.counter.saturating_sub(1);
if state.counter == 0 {
state.aux = 0;
}
}
}
pub fn tricolor_chase(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let offset = state.counter as usize;
for (i, pixel) in pixels.iter_mut().enumerate() {
*pixel = config.colors[(i + offset) % 3];
}
state.counter = state.counter.wrapping_add(1);
}
pub fn theater_chase_rainbow(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
state.aux = state.aux.wrapping_add(1) & 0xFF;
let color = color_wheel(state.aux as u8);
let offset = state.counter as usize % 3;
for (i, pixel) in pixels.iter_mut().enumerate() {
*pixel = if (i + offset) % 3 == 0 {
color
} else {
config.colors[1]
};
}
state.counter = state.counter.wrapping_add(1);
}
pub fn chase(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len();
let dot = (len / 8).max(1);
let offset = state.counter as usize % len;
for (i, pixel) in pixels.iter_mut().enumerate() {
let pos = (i + offset) % len;
*pixel = if pos < dot {
config.colors[0]
} else if pos < dot * 2 {
config.colors[1]
} else {
config.colors[2]
};
}
state.counter = state.counter.wrapping_add(1);
}
pub fn chase_random(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len();
let dot = (len / 8).max(1);
let offset = state.counter as usize % len;
if offset == 0 {
let idx = (state.aux & 0xFF) as u8;
let rng = state.aux >> 8;
let (new_idx, new_rng) = rand_wheel_index(idx, rng);
state.aux = new_idx as u32 | (new_rng << 8);
}
let color = color_wheel((state.aux & 0xFF) as u8);
for (i, pixel) in pixels.iter_mut().enumerate() {
let pos = (i + offset) % len;
*pixel = if pos < dot { color } else { WHITE };
}
state.counter = state.counter.wrapping_add(1);
}
pub fn chase_rainbow_white(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len();
let dot = (len / 8).max(1);
let offset = state.counter as usize % len;
let call = (state.aux & 0xFF) as u8;
for (i, pixel) in pixels.iter_mut().enumerate() {
let pos = (i + offset) % len;
*pixel = if pos < dot {
WHITE
} else {
color_wheel(((i * 256 / len) as u8).wrapping_add(call))
};
}
state.counter = state.counter.wrapping_add(1);
state.aux = (state.aux & !0xFF) | ((call.wrapping_add(1)) as u32);
}
pub fn chase_rainbow(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len();
let dot = (len / 8).max(1);
let color_sep = (256 / len) as u8;
let offset = state.counter as usize % len;
let call = (state.aux & 0xFF) as u8;
for (i, pixel) in pixels.iter_mut().enumerate() {
let pos = (i + offset) % len;
*pixel = if pos < dot {
color_wheel((i as u8 * color_sep).wrapping_add(call))
} else {
WHITE
};
}
state.counter = state.counter.wrapping_add(1);
state.aux = (state.aux & !0xFF) | ((call.wrapping_add(1)) as u32);
}
pub fn chase_blackout_rainbow(
pixels: &mut [RGB8],
state: &mut EffectState,
_config: &EffectConfig,
) {
let len = pixels.len();
let dot = (len / 8).max(1);
let color_sep = (256 / len) as u8;
let offset = state.counter as usize % len;
let call = (state.aux & 0xFF) as u8;
for (i, pixel) in pixels.iter_mut().enumerate() {
let pos = (i + offset) % len;
*pixel = if pos < dot {
color_wheel((i as u8 * color_sep).wrapping_add(call))
} else {
BLACK
};
}
state.counter = state.counter.wrapping_add(1);
state.aux = (state.aux & !0xFF) | ((call.wrapping_add(1)) as u32);
}
pub fn chase_flash(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len();
let pos = (state.counter / 4) as usize % len;
let flash = state.counter % 4;
for p in pixels.iter_mut() {
*p = config.colors[0];
}
if flash == 0 || flash == 2 {
pixels[pos] = config.colors[1];
}
state.counter = state.counter.wrapping_add(1);
}
pub fn chase_flash_random(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len();
let pos = (state.counter / 4) as usize % len;
let flash = state.counter % 4;
if state.counter % (len as u32 * 4) == 0 {
let idx = (state.aux & 0xFF) as u8;
let rng = state.aux >> 8;
let (new_idx, new_rng) = rand_wheel_index(idx, rng);
state.aux = new_idx as u32 | (new_rng << 8);
}
for p in pixels.iter_mut() {
*p = config.colors[0];
}
if flash == 0 || flash == 2 {
pixels[pos] = color_wheel((state.aux & 0xFF) as u8);
}
state.counter = state.counter.wrapping_add(1);
}
pub fn running(pixels: &mut [RGB8], state: &mut EffectState, config: &EffectConfig) {
let len = pixels.len();
let color = if state.counter as usize & 2 != 0 {
config.colors[0]
} else {
config.colors[1]
};
pixels.copy_within(0..len - 1, 1);
pixels[0] = color;
state.counter = state.counter.wrapping_add(1);
}
pub fn running_random(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len();
if state.counter % 4 == 0 {
let idx = (state.aux & 0xFF) as u8;
let rng = state.aux >> 8;
let (new_idx, new_rng) = rand_wheel_index(idx, rng);
state.aux = new_idx as u32 | (new_rng << 8);
}
let color = color_wheel((state.aux & 0xFF) as u8);
pixels.copy_within(0..len - 1, 1);
pixels[0] = color;
state.counter = state.counter.wrapping_add(1);
}
pub fn running_random2(pixels: &mut [RGB8], state: &mut EffectState, _config: &EffectConfig) {
let len = pixels.len();
if state.counter % 4 == 0 {
state.aux = next_rand(state.aux);
}
let color = RGB8 {
r: (state.aux >> 16) as u8,
g: (state.aux >> 8) as u8,
b: state.aux as u8,
};
pixels.copy_within(0..len - 1, 1);
pixels[0] = color;
state.counter = state.counter.wrapping_add(1);
}