diff --git a/Cargo.toml b/Cargo.toml index dab7e96..810bd42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.8.0" edition = "2021" license = "Apache-2.0" description = "Driver implementation for the WS2812 smart LED using the RP2040's PIO peripheral." -documentation = "https://docs.rs/ws2812-pio" +documentation = "https://docs.rs/ws2812-pio" repository = "https://github.com/rp-rs/ws2812-pio-rs/" [dependencies] @@ -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..e0b1a08 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ //! Bear in mind that you will have to take care of timing requirements //! yourself then. +use core::marker::PhantomData; use embedded_hal::timer::CountDown; use fugit::{ExtU32, HertzU32, MicrosDurationU32}; use rp2040_hal::{ @@ -53,7 +54,31 @@ use smart_leds_trait::SmartLedsWrite; /// delay_for_at_least_60_microseconds(); /// }; ///``` -pub struct Ws2812Direct
+/// +/// Typical RGBW usage example: +///```ignore +/// use rp2040_hal::clocks::init_clocks_and_plls; +/// let clocks = init_clocks_and_plls(...); +/// let pins = rp2040_hal::gpio::pin::bank0::Pins::new(...); +/// +/// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS); +/// let mut ws = Ws2812Direct::<_, _, _, smart_leds::RGBA8>::new( +/// pins.gpio4.into_mode(), +/// &mut pio, +/// sm0, +/// clocks.peripheral_clock.freq(), +/// ); +/// +/// // Then you will make sure yourself to not write too frequently: +/// loop { +/// use smart_leds::{SmartLedsWrite, RGBA8}; +/// let color : RGBA8 = (255, 0, 255, 127).into(); +/// +/// ws.write([color].iter().copied()).unwrap(); +/// delay_for_at_least_60_microseconds(); +/// }; +///``` +pub struct Ws2812Direct
where
I: AnyPin Ws2812Direct
+impl Ws2812Direct
where
I: AnyPin SmartLedsWrite for Ws2812Direct
+/// Specify whether to use 3 or 4 bytes per led color.
+pub enum ColorBytes {
+ ThreeBytes,
+ FourBytes,
+}
+
+impl ColorBytes {
+ const fn num_bits(&self) -> u8 {
+ match self {
+ ColorBytes::ThreeBytes => 24,
+ ColorBytes::FourBytes => 32,
+ }
+ }
+}
+
+/// Implement this trait to support a user-defined color format.
+///
+/// smart_leds::RGB8 and smart_leds::RGBA are implemented by the ws2812-pio
+/// crate.
+pub trait ColorFormat {
+ /// Select the number of bytes per led.
+ const COLOR_BYTES: ColorBytes;
+
+ /// Map the color to a 32-bit word.
+ fn to_word(self) -> u32;
+}
+
+impl ColorFormat for smart_leds_trait::RGB8 {
+ const COLOR_BYTES: ColorBytes = ColorBytes::ThreeBytes;
+ fn to_word(self) -> u32 {
+ (u32::from(self.g) << 24) | (u32::from(self.r) << 16) | (u32::from(self.b) << 8)
+ }
+}
+
+impl ColorFormat for smart_leds_trait::RGBA SmartLedsWrite for Ws2812Direct
where
I: AnyPin
+///
+/// Typical RGBW usage example:
+///```ignore
+/// use rp2040_hal::clocks::init_clocks_and_plls;
+/// let clocks = init_clocks_and_plls(...);
+/// let pins = rp2040_hal::gpio::pin::bank0::Pins::new(...);
+///
+/// let timer = Timer::new(pac.TIMER, &mut pac.RESETS);
+///
+/// let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
+/// let mut ws = Ws2812::<_, _, _, _, smart_leds::RGBA8>::new(
+/// pins.gpio4.into_mode(),
+/// &mut pio,
+/// sm0,
+/// clocks.peripheral_clock.freq(),
+/// timer.count_down(),
+/// );
+///
+/// loop {
+/// use smart_leds::{SmartLedsWrite, RGBA8};
+/// let color : RGBA8 = (255, 0, 255, 127).into();
+///
+/// ws.write([color].iter().copied()).unwrap();
+///
+/// // Do other stuff here...
+/// };
+///```
+pub struct Ws2812
where
C: CountDown,
I: AnyPin ,
+ driver: Ws2812Direct ,
cd: C,
}
-impl Ws2812
+impl Ws2812
where
C: CountDown,
I: AnyPin {
+ ) -> Ws2812 {
let driver = Ws2812Direct::new(pin, pio, sm, clock_freq);
Self { driver, cd }
}
}
-impl SmartLedsWrite for Ws2812
+impl SmartLedsWrite for Ws2812
where
C: CountDown,
C::Time: From