diff --git a/Cargo.toml b/Cargo.toml index 6e8abe5..4b6668f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.9.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] diff --git a/src/lib.rs b/src/lib.rs index 75ad292..a201d27 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::{ @@ -54,7 +55,31 @@ use smart_leds_trait_0_2::SmartLedsWrite as SmartLedsWrite02; /// delay_for_at_least_60_microseconds(); /// }; ///``` -pub struct Ws2812Direct
+/// +/// Usage for RGBW devices is similar: +///```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::new_sk6812( +/// 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, RGBW, White}; +/// let color = RGBW { r: 255, g: 0, b: 255, w: White(127) }; +/// +/// ws.write([color]).unwrap(); +/// delay_for_at_least_60_microseconds(); +/// }; +///``` +pub struct Ws2812Direct
where
I: AnyPin Ws2812Direct
+impl Ws2812Direct
where
I: AnyPin ,
sm: UninitStateMachine<(P, SM)>,
- clock_freq: fugit::HertzU32,
+ clock_freq: HertzU32,
) -> Self {
// prepare the PIO program
let side_set = pio::SideSet::new(false, 1, false);
@@ -134,7 +160,7 @@ where
// OSR config
.out_shift_direction(rp2040_hal::pio::ShiftDirection::Left)
.autopull(true)
- .pull_threshold(24)
+ .pull_threshold( SmartLedsWrite for Ws2812Direct
+impl Ws2812Direct
where
I: AnyPin ,
+ sm: UninitStateMachine<(P, SM)>,
+ clock_freq: HertzU32,
+ ) -> Self {
+ Self::new_generic(pin, pio, sm, clock_freq)
+ }
+}
+
+impl Ws2812Direct >
+where
+ I: AnyPin ,
+ sm: UninitStateMachine<(P, SM)>,
+ clock_freq: HertzU32,
+ ) -> Self {
+ Self::new_generic(pin, pio, sm, clock_freq)
+ }
+}
+
+/// 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::RGBW SmartLedsWrite for Ws2812Direct
+where
+ I: AnyPin
+///
+/// Usage for RGBW devices is similar:
+///```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::new_sk6812(
+/// pins.gpio4.into_mode(),
+/// &mut pio,
+/// sm0,
+/// clocks.peripheral_clock.freq(),
+/// timer.count_down(),
+/// );
+///
+/// loop {
+/// use smart_leds::{SmartLedsWrite, RGBW, White};
+/// let color = RGBW { r: 255, g: 0, b: 255, w: White(127) };
+///
+/// ws.write([color]).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 ,
sm: UninitStateMachine<(P, SM)>,
- clock_freq: fugit::HertzU32,
+ clock_freq: HertzU32,
cd: C,
- ) -> Ws2812 {
+ ) -> Ws2812 {
let driver = Ws2812Direct::new(pin, pio, sm, clock_freq);
Self { driver, cd }
}
}
-impl SmartLedsWrite for Ws2812
+impl Ws2812 >
+where
+ C: CountDown,
+ I: AnyPin ,
+ sm: UninitStateMachine<(P, SM)>,
+ clock_freq: HertzU32,
+ cd: C,
+ ) -> Ws2812 > {
+ let driver = Ws2812Direct::new_sk6812(pin, pio, sm, clock_freq);
+
+ Self { driver, cd }
+ }
+}
+
+impl SmartLedsWrite for Ws2812
where
C: CountDown,
C::Time: From