holiday_lights/lights/src/lib.rs

61 lines
2.3 KiB
Rust

//! Abstractions for working with individually-addressible LED light strands, such as WS2811 lights.
//!
//! An output driver implements the [Lights] trait, which you feed pixel values of a compatible type.
//! The [rgb] module contains some basic color-manipulation tools, and the [gamma] module supports
//! converting perceptual to physical color space for output.
#![no_std]
pub mod gamma;
pub mod rgb;
use core::borrow::Borrow;
/// An RGB value in physical color space, which should be passed on to an LED for display.
/// Not suitable for color operations, since its values won't be perceptually linear.
/// See the [rgb] module for the former, and the [gamma] module to convert into this.
#[derive(Clone, Copy, PartialEq)]
pub struct HardwareRgb(pub u8, pub u8, pub u8);
/// Represents a string of lights which can be individually updated in linear order.
pub trait Lights {
/// The type of value each light in the strand can take.
///
/// Probably either a [rgb::Rgb] (pre-gamma correction) or [HardwareRgb] (post-gamma correction),
/// but in theory monochrome LEDs might take a numeric type, or bools for a strand without even brightness control.
type Pixel;
/// Send a pixel value to the next light in the string.
///
/// Updating a string is likely a time-sensitive operation, so aim to keep this in a tight loop.
/// (WS2811 and similar lighting will latch after the data line is quiet long enough)
fn render(&mut self, pixel: &Self::Pixel);
/// Indicate that all pixels have been updated, and the next render() should start at the beginning again.
fn latch(&mut self);
}
/// Extension trait to fluently dump an iterator of pixels into a light strand.
pub trait PixelIterator<T: Lights> {
/// Display all pixel from this iterator onto the given strand.
/// Does *not* call [Lights::latch].
fn render_to(&mut self, lights: &mut T);
}
impl<T: Lights, I: Iterator> PixelIterator<T> for I
where I::Item: Borrow<T::Pixel>
{
#[inline]
fn render_to(&mut self, lights: &mut T) {
self.for_each(|pixel| lights.render(pixel.borrow()));
}
}
pub fn murmurf(state: &mut u32) -> u32 {
*state ^= *state >> 16;
*state *= 0x85ebca6b;
*state ^= *state >> 13;
*state *= 0xc2b2ae35;
*state ^= *state >> 16;
return *state;
}