ws2812_esp32_rmt_driver/driver/
color.rs

1//! device-dependant LED pixel colors
2
3/// LED pixel color trait
4pub trait LedPixelColor:
5    Ord + PartialOrd + Eq + PartialEq + Clone + Sync + AsRef<[u8]> + AsMut<[u8]>
6{
7    /// byte per pixel. e.g. 3 for typical RGB.
8    const BPP: usize;
9    /// Creates with RGB (Red-Green-Blue) value.
10    fn new_with_rgb(r: u8, g: u8, b: u8) -> Self;
11    /// Creates with RGBW (Red-Green-Blue, and White) value.
12    fn new_with_rgbw(r: u8, g: u8, b: u8, w: u8) -> Self;
13    /// Returns Red channel value
14    fn r(&self) -> u8;
15    /// Returns Green channel value
16    fn g(&self) -> u8;
17    /// Returns Blue channel value
18    fn b(&self) -> u8;
19    /// Returns White channel value
20    fn w(&self) -> u8;
21
22    /// Returns brightness-adjusted color.
23    /// Each channel values of the returned shall be scaled down to `(brightness + 1) / 256`.
24    #[inline]
25    fn brightness(&self, brightness: u8) -> Self {
26        Self::new_with_rgbw(
27            ((self.r() as u16) * (brightness as u16 + 1) / 256) as u8,
28            ((self.g() as u16) * (brightness as u16 + 1) / 256) as u8,
29            ((self.b() as u16) * (brightness as u16 + 1) / 256) as u8,
30            ((self.w() as u16) * (brightness as u16 + 1) / 256) as u8,
31        )
32    }
33}
34
35/// LED pixel color struct made with an `N`-length `u8` array.
36///
37/// * `N` - Byte per pixel. equals to [`BPP`](#associatedconstant.BPP).
38/// * `R_ORDER` - Index of the Red. Specify the value larger than `N - 1` if absent.
39/// * `G_ORDER` - Index of the Green. Specify the value larger than `N - 1` if absent.
40/// * `B_ORDER` - Index of the Blue. Specify the value larger than `N - 1` if absent.
41/// * `W_ORDER` - Index of the White. Specify the value larger than `N - 1` if absent.
42///
43/// # Examples
44///
45/// ```
46/// use ws2812_esp32_rmt_driver::driver::color::{LedPixelColorImpl, LedPixelColor};
47///
48/// let color = LedPixelColorImpl::<3, 1, 0, 2, 255>::new_with_rgb(1, 2, 3);
49/// assert_eq!(color.as_ref(), [2, 1, 3]);
50/// assert_eq!((color.r(), color.g(), color.b(), color.w()), (1, 2, 3, 0));
51/// ```
52#[derive(Ord, PartialOrd, Eq, PartialEq, Clone, Hash)]
53#[repr(transparent)]
54pub struct LedPixelColorImpl<
55    const N: usize,
56    const R_ORDER: usize,
57    const G_ORDER: usize,
58    const B_ORDER: usize,
59    const W_ORDER: usize,
60>(pub(crate) [u8; N]);
61
62impl<
63        const N: usize,
64        const R_ORDER: usize,
65        const G_ORDER: usize,
66        const B_ORDER: usize,
67        const W_ORDER: usize,
68    > LedPixelColor for LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>
69{
70    const BPP: usize = N;
71
72    #[inline]
73    fn new_with_rgb(r: u8, g: u8, b: u8) -> Self {
74        Self::new_with_rgbw(r, g, b, 0)
75    }
76
77    #[inline]
78    fn new_with_rgbw(r: u8, g: u8, b: u8, w: u8) -> Self {
79        let mut array = [0; N];
80        if let Some(v) = array.get_mut(R_ORDER) {
81            *v = r;
82        }
83        if let Some(v) = array.get_mut(G_ORDER) {
84            *v = g;
85        }
86        if let Some(v) = array.get_mut(B_ORDER) {
87            *v = b;
88        }
89        if let Some(v) = array.get_mut(W_ORDER) {
90            *v = w;
91        }
92        Self(array)
93    }
94
95    #[inline]
96    fn r(&self) -> u8 {
97        self.0.get(R_ORDER).cloned().unwrap_or(0)
98    }
99
100    #[inline]
101    fn g(&self) -> u8 {
102        self.0.get(G_ORDER).cloned().unwrap_or(0)
103    }
104
105    #[inline]
106    fn b(&self) -> u8 {
107        self.0.get(B_ORDER).cloned().unwrap_or(0)
108    }
109
110    #[inline]
111    fn w(&self) -> u8 {
112        self.0.get(W_ORDER).cloned().unwrap_or(0)
113    }
114}
115
116impl<
117        const N: usize,
118        const R_ORDER: usize,
119        const G_ORDER: usize,
120        const B_ORDER: usize,
121        const W_ORDER: usize,
122    > Default for LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>
123{
124    /// Returns the black color (All LED OFF)
125    #[inline]
126    fn default() -> Self {
127        Self([0; N])
128    }
129}
130
131impl<
132        const N: usize,
133        const R_ORDER: usize,
134        const G_ORDER: usize,
135        const B_ORDER: usize,
136        const W_ORDER: usize,
137    > AsRef<[u8]> for LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>
138{
139    fn as_ref(&self) -> &[u8] {
140        &self.0
141    }
142}
143
144impl<
145        const N: usize,
146        const R_ORDER: usize,
147        const G_ORDER: usize,
148        const B_ORDER: usize,
149        const W_ORDER: usize,
150    > AsMut<[u8]> for LedPixelColorImpl<N, R_ORDER, G_ORDER, B_ORDER, W_ORDER>
151{
152    fn as_mut(&mut self) -> &mut [u8] {
153        &mut self.0
154    }
155}
156
157#[test]
158fn test_led_pixel_color_impl() {
159    let color = LedPixelColorImpl::<3, 1, 0, 2, 255>::new_with_rgb(1, 2, 3);
160    assert_eq!(color.0, [2, 1, 3]);
161    assert_eq!(color.as_ref(), &color.0);
162    assert_eq!((color.r(), color.g(), color.b(), color.w()), (1, 2, 3, 0));
163
164    let color = LedPixelColorImpl::<3, 1, 0, 2, 255>::new_with_rgbw(1, 2, 3, 4);
165    assert_eq!(color.0, [2, 1, 3]);
166    assert_eq!(color.as_ref(), &color.0);
167    assert_eq!((color.r(), color.g(), color.b(), color.w()), (1, 2, 3, 0));
168
169    let color = LedPixelColorImpl::<4, 0, 1, 2, 3>::new_with_rgb(1, 2, 3);
170    assert_eq!(color.0, [1, 2, 3, 0]);
171    assert_eq!(color.as_ref(), &color.0);
172    assert_eq!((color.r(), color.g(), color.b(), color.w()), (1, 2, 3, 0));
173
174    let color = LedPixelColorImpl::<4, 0, 1, 2, 3>::new_with_rgbw(1, 2, 3, 4);
175    assert_eq!(color.0, [1, 2, 3, 4]);
176    assert_eq!(color.as_ref(), &color.0);
177    assert_eq!((color.r(), color.g(), color.b(), color.w()), (1, 2, 3, 4));
178}
179
180#[test]
181fn test_led_pixel_color_brightness() {
182    let color = LedPixelColorImpl::<4, 0, 1, 2, 3>::new_with_rgbw(255, 128, 64, 32).brightness(128);
183    assert_eq!(
184        (color.r(), color.g(), color.b(), color.w()),
185        (128, 64, 32, 16)
186    );
187}
188
189/// 8-bit GRB LED pixel color (total 32-bit pixel), Typical RGB LED (WS2812B/SK6812) pixel color
190///
191/// # Examples
192///
193/// ```
194/// use ws2812_esp32_rmt_driver::driver::color::{LedPixelColorGrb24, LedPixelColor};
195///
196/// let color = LedPixelColorGrb24::new_with_rgb(1, 2, 3);
197/// assert_eq!(color.as_ref(), [2, 1, 3]);
198/// ```
199pub type LedPixelColorGrb24 = LedPixelColorImpl<3, 1, 0, 2, 255>;
200
201/// 8-bit RGBW LED pixel color (total 32-bit pixel)
202///
203/// # Examples
204///
205/// ```
206/// use ws2812_esp32_rmt_driver::driver::color::{LedPixelColorRgbw32, LedPixelColor};
207///
208/// let color = LedPixelColorRgbw32::new_with_rgbw(1, 2, 3, 4);
209/// assert_eq!(color.as_ref(), [1, 2, 3, 4]);
210/// ```
211pub type LedPixelColorRgbw32 = LedPixelColorImpl<4, 0, 1, 2, 3>;
212
213/// 8-bit GRBW LED pixel color (total 32-bit pixel)
214///
215/// # Examples
216///
217/// ```
218/// use ws2812_esp32_rmt_driver::driver::color::{LedPixelColorGrbw32, LedPixelColor};
219///
220/// let color = LedPixelColorGrbw32::new_with_rgbw(1, 2, 3, 4);
221/// assert_eq!(color.as_ref(), [2, 1, 3, 4]);
222/// ```
223pub type LedPixelColorGrbw32 = LedPixelColorImpl<4, 1, 0, 2, 3>;