1use crate::driver::color::{LedPixelColor, LedPixelColorGrb24, LedPixelColorImpl};
4use crate::driver::{Ws2812Esp32RmtDriver, Ws2812Esp32RmtDriverError};
5#[cfg(all(not(feature = "std"), feature = "alloc"))]
6use alloc::vec::Vec;
7use esp_idf_hal::rmt::TxRmtDriver;
8use core::marker::PhantomData;
9#[cfg(feature = "alloc")]
10use smart_leds_trait::SmartLedsWrite;
11use smart_leds_trait::{RGB8, RGBW};
12
13#[cfg(not(target_vendor = "espressif"))]
14use crate::mock::esp_idf_hal;
15use esp_idf_hal::{gpio::OutputPin, peripheral::Peripheral, rmt::RmtChannel};
16
17pub type RGBW8 = RGBW<u8, u8>;
19
20impl<
21 const N: usize,
22 const R_ORDER: usize,
23 const G_ORDER: usize,
24 const B_ORDER: usize,
25 const W_ORDER: usize,
26 > From<RGB8> for LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>
27{
28 fn from(x: RGB8) -> Self {
29 Self::new_with_rgb(x.r, x.g, x.b)
30 }
31}
32
33impl<
34 const N: usize,
35 const R_ORDER: usize,
36 const G_ORDER: usize,
37 const B_ORDER: usize,
38 const W_ORDER: usize,
39 > From<RGBW8> for LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>
40{
41 fn from(x: RGBW8) -> Self {
42 Self::new_with_rgbw(x.r, x.g, x.b, x.a.0)
43 }
44}
45
46pub struct LedPixelEsp32Rmt<'d, CSmart, CDev>
71where
72 CDev: LedPixelColor + From<CSmart>,
73{
74 driver: Ws2812Esp32RmtDriver<'d>,
75 phantom: PhantomData<(CSmart, CDev)>,
76}
77
78impl<'d, CSmart, CDev> LedPixelEsp32Rmt<'d, CSmart, CDev>
79where
80 CDev: LedPixelColor + From<CSmart>,
81{
82 pub fn new<C: RmtChannel>(
86 channel: impl Peripheral<P = C> + 'd,
87 pin: impl Peripheral<P = impl OutputPin> + 'd,
88 ) -> Result<Self, Ws2812Esp32RmtDriverError> {
89 let driver = Ws2812Esp32RmtDriver::<'d>::new(channel, pin)?;
90 Ok(Self {
91 driver,
92 phantom: Default::default(),
93 })
94 }
95
96 pub fn new_with_rmt_driver(
98 tx: TxRmtDriver<'d>,
99 ) -> Result<Self, Ws2812Esp32RmtDriverError> {
100 let driver = Ws2812Esp32RmtDriver::<'d>::new_with_rmt_driver(tx)?;
101 Ok(Self {
102 driver,
103 phantom: Default::default(),
104 })
105 }
106}
107
108impl<
109 'd,
110 CSmart,
111 const N: usize,
112 const R_ORDER: usize,
113 const G_ORDER: usize,
114 const B_ORDER: usize,
115 const W_ORDER: usize,
116 > LedPixelEsp32Rmt<'d, CSmart, LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>>
117where
118 LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>: From<CSmart>,
119{
120 pub fn write_nocopy<T, I>(&mut self, iterator: T) -> Result<(), Ws2812Esp32RmtDriverError>
126 where
127 T: IntoIterator<Item = I>,
128 I: Into<CSmart>,
129 <T as IntoIterator>::IntoIter: Send,
130 {
131 self.driver
132 .write_blocking(iterator.into_iter().flat_map(|color| {
133 let c =
134 LedPixelColorImpl::<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>::from(color.into());
135 c.0
136 }))?;
137 Ok(())
138 }
139}
140
141#[cfg(feature = "alloc")]
142impl<'d, CSmart, CDev> SmartLedsWrite for LedPixelEsp32Rmt<'d, CSmart, CDev>
143where
144 CDev: LedPixelColor + From<CSmart>,
145{
146 type Error = Ws2812Esp32RmtDriverError;
147 type Color = CSmart;
148
149 fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error>
155 where
156 T: IntoIterator<Item = I>,
157 I: Into<Self::Color>,
158 {
159 let pixel_data = iterator.into_iter().fold(Vec::new(), |mut vec, color| {
160 vec.extend_from_slice(CDev::from(color.into()).as_ref());
161 vec
162 });
163 self.driver.write_blocking(pixel_data.into_iter())?;
164 Ok(())
165 }
166}
167
168pub type Ws2812Esp32Rmt<'d> = LedPixelEsp32Rmt<'d, RGB8, LedPixelColorGrb24>;
190
191#[cfg(test)]
192mod test {
193 use super::*;
194 use crate::mock::esp_idf_hal::peripherals::Peripherals;
195
196 #[test]
197 fn test_ws2812_esp32_rmt_smart_leds() {
198 let sample_data = [RGB8::new(0x00, 0x01, 0x02), RGB8::new(0x03, 0x04, 0x05)];
199 let expected_values: [u8; 6] = [0x01, 0x00, 0x02, 0x04, 0x03, 0x05];
200
201 let peripherals = Peripherals::take().unwrap();
202 let led_pin = peripherals.pins.gpio0;
203 let channel = peripherals.rmt.channel0;
204
205 let mut ws2812 = Ws2812Esp32Rmt::new(channel, led_pin).unwrap();
206 ws2812.write(sample_data.iter().cloned()).unwrap();
207 assert_eq!(ws2812.driver.pixel_data.unwrap(), &expected_values);
208 }
209}