diff --git a/Cargo.toml b/Cargo.toml index dab7e96..dab870c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ws2812-pio" -version = "0.8.0" +version = "0.9.1" edition = "2021" license = "Apache-2.0" description = "Driver implementation for the WS2812 smart LED using the RP2040's PIO peripheral." @@ -12,6 +12,6 @@ embedded-hal = "0.2.5" fugit = "0.3.5" rp2040-hal = "0.10" pio = "0.2.0" -smart-leds-trait = "0.2.1" +smart-leds-trait = "0.3.0" nb = "1.0.0" cortex-m = "0.7.3" diff --git a/src/lib.rs b/src/lib.rs index acc6481..d739f0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,10 +49,26 @@ use smart_leds_trait::SmartLedsWrite; /// use smart_leds::{SmartLedsWrite, RGB8}; /// let color : RGB8 = (255, 0, 255).into(); /// -/// ws.write([color].iter().copied()).unwrap(); +/// ws.write([color]).unwrap(); /// delay_for_at_least_60_microseconds(); /// }; ///``` +/// +/// // It is possible to change the color ordering by using +/// // the constructor ```new_with_chip_config``` along with the +/// // ordering enum ```Ws2812ColorOrder```: +///```ignore +/// let mut ws = Ws2812Direct::new_with_chip_config( +/// pins.gpio4.into_mode(), +/// &mut pio, +/// sm0, +/// clocks.peripheral_clock.freq(), +/// Ws2812ColorOrder::RGB, +/// ); +/// ``` +mod ws2812_color_order; +pub use ws2812_color_order::Ws2812ColorOrder; + pub struct Ws2812Direct where I: AnyPin, @@ -61,6 +77,7 @@ where { tx: Tx<(P, SM)>, _pin: I, + _converter: Ws2812ColorOrder, } impl Ws2812Direct @@ -75,6 +92,16 @@ where pio: &mut PIO

, sm: UninitStateMachine<(P, SM)>, clock_freq: fugit::HertzU32, + ) -> Self { + Ws2812Direct::new_with_chip_config(pin, pio, sm, clock_freq, Ws2812ColorOrder::GRB) + } + /// Creates a new instance of this driver. + pub fn new_with_chip_config( + pin: I, + pio: &mut PIO

, + sm: UninitStateMachine<(P, SM)>, + clock_freq: fugit::HertzU32, + chip_config: Ws2812ColorOrder, ) -> Self { // prepare the PIO program let side_set = pio::SideSet::new(false, 1, false); @@ -145,6 +172,7 @@ where Self { tx, _pin: I::from(pin), + _converter: chip_config, } } } @@ -166,15 +194,13 @@ where /// PIO FIFO until all data has been transmitted to the LED chain. fn write(&mut self, iterator: T) -> Result<(), ()> where - T: Iterator, + T: IntoIterator, J: Into, { for item in iterator { let color: Self::Color = item.into(); - let word = - (u32::from(color.g) << 24) | (u32::from(color.r) << 16) | (u32::from(color.b) << 8); - while !self.tx.write(word) { + while !self.tx.write(self._converter._get_color_value(&color)) { cortex_m::asm::nop(); } } @@ -212,6 +238,20 @@ where /// // Do other stuff here... /// }; ///``` +/// +/// // It is possible to change the color ordering by using +/// // the constructor ```new_with_chip_config``` along with the +/// // ordering enum ```Ws2812ColorOrder```: +///```ignore +/// let mut ws = Ws2812::new_with_chip_config( +/// pins.gpio4.into_mode(), +/// &mut pio, +/// sm0, +/// clocks.peripheral_clock.freq(), +/// timer.count_down(), +/// Ws2812ColorOrder::RGB, +/// ); +/// ``` pub struct Ws2812 where C: CountDown, @@ -242,6 +282,20 @@ where Self { driver, cd } } + + /// Creates a new instance of this driver. + pub fn new_with_chip_config( + pin: I, + pio: &mut PIO

, + sm: UninitStateMachine<(P, SM)>, + clock_freq: fugit::HertzU32, + cd: C, + chip_config: Ws2812ColorOrder, + ) -> Ws2812 { + let driver = Ws2812Direct::new_with_chip_config(pin, pio, sm, clock_freq, chip_config); + + Self { driver, cd } + } } impl SmartLedsWrite for Ws2812 @@ -256,7 +310,7 @@ where type Error = (); fn write(&mut self, iterator: T) -> Result<(), ()> where - T: Iterator, + T: IntoIterator, J: Into, { self.driver.tx.clear_stalled_flag(); diff --git a/src/ws2812_color_order.rs b/src/ws2812_color_order.rs new file mode 100644 index 0000000..5518087 --- /dev/null +++ b/src/ws2812_color_order.rs @@ -0,0 +1,46 @@ +#[derive(Copy, Clone)] +pub enum Ws2812ColorOrder { + RGB, + GRB, + RBG, + BGR, + GBR, + BRG, +} + +impl Ws2812ColorOrder { + pub fn _get_color_value(&self, color: &smart_leds_trait::RGB8) -> u32 { + match self { + Ws2812ColorOrder::RGB => { + return (u32::from(color.r) << 24) + | (u32::from(color.g) << 16) + | (u32::from(color.b) << 8) + } + Ws2812ColorOrder::GRB => { + return (u32::from(color.g) << 24) + | (u32::from(color.r) << 16) + | (u32::from(color.b) << 8) + } + Ws2812ColorOrder::RBG => { + return (u32::from(color.r) << 24) + | (u32::from(color.b) << 16) + | (u32::from(color.g) << 8) + } + Ws2812ColorOrder::BGR => { + return (u32::from(color.b) << 24) + | (u32::from(color.g) << 16) + | (u32::from(color.r) << 8) + } + Ws2812ColorOrder::GBR => { + return (u32::from(color.g) << 24) + | (u32::from(color.b) << 16) + | (u32::from(color.r) << 8) + } + Ws2812ColorOrder::BRG => { + return (u32::from(color.b) << 24) + | (u32::from(color.r) << 16) + | (u32::from(color.g) << 8) + } + }; + } +}