1- //! [ws2812](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf )
1+ //! [ws2812](https://www.sparkfun.com/categories/tags/ws2812 )
22
33use embassy_time:: Timer ;
44use fixed:: types:: U24F8 ;
@@ -16,6 +16,54 @@ const T2: u8 = 5; // data bit
1616const T3 : u8 = 3 ; // stop bit
1717const CYCLES_PER_BIT : u32 = ( T1 + T2 + T3 ) as u32 ;
1818
19+ /// Color orders for WS2812B, type RGB8
20+ pub trait RgbColorOrder {
21+ /// Pack an 8-bit RGB color into a u32
22+ fn pack ( color : RGB8 ) -> u32 ;
23+ }
24+
25+ /// Green, Red, Blue order is the common default for WS2812B
26+ pub struct Grb ;
27+ impl RgbColorOrder for Grb {
28+ /// Pack an 8-bit RGB color into a u32 in GRB order
29+ fn pack ( color : RGB8 ) -> u32 {
30+ ( u32:: from ( color. g ) << 24 ) | ( u32:: from ( color. r ) << 16 ) | ( u32:: from ( color. b ) << 8 )
31+ }
32+ }
33+
34+ /// Red, Green, Blue is used by some WS2812B implementations
35+ pub struct Rgb ;
36+ impl RgbColorOrder for Rgb {
37+ /// Pack an 8-bit RGB color into a u32 in RGB order
38+ fn pack ( color : RGB8 ) -> u32 {
39+ ( u32:: from ( color. r ) << 24 ) | ( u32:: from ( color. g ) << 16 ) | ( u32:: from ( color. b ) << 8 )
40+ }
41+ }
42+
43+ /// Color orders RGBW strips
44+ pub trait RgbwColorOrder {
45+ /// Pack an RGB+W color into a u32
46+ fn pack ( color : RGBW < u8 > ) -> u32 ;
47+ }
48+
49+ /// Green, Red, Blue, White order is the common default for RGBW strips
50+ pub struct Grbw ;
51+ impl RgbwColorOrder for Grbw {
52+ /// Pack an RGB+W color into a u32 in GRBW order
53+ fn pack ( color : RGBW < u8 > ) -> u32 {
54+ ( u32:: from ( color. g ) << 24 ) | ( u32:: from ( color. r ) << 16 ) | ( u32:: from ( color. b ) << 8 ) | u32:: from ( color. a . 0 )
55+ }
56+ }
57+
58+ /// Red, Green, Blue, White order
59+ pub struct Rgbw ;
60+ impl RgbwColorOrder for Rgbw {
61+ /// Pack an RGB+W color into a u32 in RGBW order
62+ fn pack ( color : RGBW < u8 > ) -> u32 {
63+ ( u32:: from ( color. r ) << 24 ) | ( u32:: from ( color. g ) << 16 ) | ( u32:: from ( color. b ) << 8 ) | u32:: from ( color. a . 0 )
64+ }
65+ }
66+
1967/// This struct represents a ws2812 program loaded into pio instruction memory.
2068pub struct PioWs2812Program < ' a , PIO : Instance > {
2169 prg : LoadedProgram < ' a , PIO > ,
@@ -52,14 +100,36 @@ impl<'a, PIO: Instance> PioWs2812Program<'a, PIO> {
52100
53101/// Pio backed RGB ws2812 driver
54102/// Const N is the number of ws2812 leds attached to this pin
55- pub struct PioWs2812 < ' d , P : Instance , const S : usize , const N : usize > {
103+ pub struct PioWs2812 < ' d , P : Instance , const S : usize , const N : usize , ORDER >
104+ where
105+ ORDER : RgbColorOrder ,
106+ {
56107 dma : Peri < ' d , AnyChannel > ,
57108 sm : StateMachine < ' d , P , S > ,
109+ _order : core:: marker:: PhantomData < ORDER > ,
58110}
59111
60- impl < ' d , P : Instance , const S : usize , const N : usize > PioWs2812 < ' d , P , S , N > {
112+ impl < ' d , P : Instance , const S : usize , const N : usize > PioWs2812 < ' d , P , S , N , Grb > {
61113 /// Configure a pio state machine to use the loaded ws2812 program.
114+ /// Uses the default GRB order.
62115 pub fn new (
116+ pio : & mut Common < ' d , P > ,
117+ sm : StateMachine < ' d , P , S > ,
118+ dma : Peri < ' d , impl Channel > ,
119+ pin : Peri < ' d , impl PioPin > ,
120+ program : & PioWs2812Program < ' d , P > ,
121+ ) -> Self {
122+ Self :: with_color_order ( pio, sm, dma, pin, program)
123+ }
124+ }
125+
126+ impl < ' d , P : Instance , const S : usize , const N : usize , ORDER > PioWs2812 < ' d , P , S , N , ORDER >
127+ where
128+ ORDER : RgbColorOrder ,
129+ {
130+ /// Configure a pio state machine to use the loaded ws2812 program.
131+ /// Uses the specified color order.
132+ pub fn with_color_order (
63133 pio : & mut Common < ' d , P > ,
64134 mut sm : StateMachine < ' d , P , S > ,
65135 dma : Peri < ' d , impl Channel > ,
@@ -93,16 +163,19 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
93163 sm. set_config ( & cfg) ;
94164 sm. set_enable ( true ) ;
95165
96- Self { dma : dma. into ( ) , sm }
166+ Self {
167+ dma : dma. into ( ) ,
168+ sm,
169+ _order : core:: marker:: PhantomData ,
170+ }
97171 }
98172
99173 /// Write a buffer of [smart_leds::RGB8] to the ws2812 string
100174 pub async fn write ( & mut self , colors : & [ RGB8 ; N ] ) {
101175 // Precompute the word bytes from the colors
102176 let mut words = [ 0u32 ; N ] ;
103177 for i in 0 ..N {
104- let word = ( u32:: from ( colors[ i] . g ) << 24 ) | ( u32:: from ( colors[ i] . r ) << 16 ) | ( u32:: from ( colors[ i] . b ) << 8 ) ;
105- words[ i] = word;
178+ words[ i] = ORDER :: pack ( colors[ i] ) ;
106179 }
107180
108181 // DMA transfer
@@ -115,14 +188,36 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
115188/// Pio backed RGBW ws2812 driver
116189/// This version is intended for ws2812 leds with 4 addressable lights
117190/// Const N is the number of ws2812 leds attached to this pin
118- pub struct RgbwPioWs2812 < ' d , P : Instance , const S : usize , const N : usize > {
191+ pub struct RgbwPioWs2812 < ' d , P : Instance , const S : usize , const N : usize , ORDER >
192+ where
193+ ORDER : RgbwColorOrder ,
194+ {
119195 dma : Peri < ' d , AnyChannel > ,
120196 sm : StateMachine < ' d , P , S > ,
197+ _order : core:: marker:: PhantomData < ORDER > ,
121198}
122199
123- impl < ' d , P : Instance , const S : usize , const N : usize > RgbwPioWs2812 < ' d , P , S , N > {
200+ impl < ' d , P : Instance , const S : usize , const N : usize > RgbwPioWs2812 < ' d , P , S , N , Grbw > {
124201 /// Configure a pio state machine to use the loaded ws2812 program.
202+ /// Uses the default GRBW color order
125203 pub fn new (
204+ pio : & mut Common < ' d , P > ,
205+ sm : StateMachine < ' d , P , S > ,
206+ dma : Peri < ' d , impl Channel > ,
207+ pin : Peri < ' d , impl PioPin > ,
208+ program : & PioWs2812Program < ' d , P > ,
209+ ) -> Self {
210+ Self :: with_color_order ( pio, sm, dma, pin, program)
211+ }
212+ }
213+
214+ impl < ' d , P : Instance , const S : usize , const N : usize , ORDER > RgbwPioWs2812 < ' d , P , S , N , ORDER >
215+ where
216+ ORDER : RgbwColorOrder ,
217+ {
218+ /// Configure a pio state machine to use the loaded ws2812 program.
219+ /// Uses the specified color order
220+ pub fn with_color_order (
126221 pio : & mut Common < ' d , P > ,
127222 mut sm : StateMachine < ' d , P , S > ,
128223 dma : Peri < ' d , impl Channel > ,
@@ -156,19 +251,19 @@ impl<'d, P: Instance, const S: usize, const N: usize> RgbwPioWs2812<'d, P, S, N>
156251 sm. set_config ( & cfg) ;
157252 sm. set_enable ( true ) ;
158253
159- Self { dma : dma. into ( ) , sm }
254+ Self {
255+ dma : dma. into ( ) ,
256+ sm,
257+ _order : core:: marker:: PhantomData ,
258+ }
160259 }
161260
162261 /// Write a buffer of [smart_leds::RGBW] to the ws2812 string
163262 pub async fn write ( & mut self , colors : & [ RGBW < u8 > ; N ] ) {
164263 // Precompute the word bytes from the colors
165264 let mut words = [ 0u32 ; N ] ;
166265 for i in 0 ..N {
167- let word = ( u32:: from ( colors[ i] . g ) << 24 )
168- | ( u32:: from ( colors[ i] . r ) << 16 )
169- | ( u32:: from ( colors[ i] . b ) << 8 )
170- | u32:: from ( colors[ i] . a . 0 ) ;
171- words[ i] = word;
266+ words[ i] = ORDER :: pack ( colors[ i] ) ;
172267 }
173268
174269 // DMA transfer
0 commit comments