Skip to content

Commit 4653555

Browse files
Add pixel order functionality
Should be backwards compatible
1 parent 0722bfc commit 4653555

File tree

3 files changed

+98
-37
lines changed

3 files changed

+98
-37
lines changed

src/hosted.rs

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ use smart_leds_trait::{SmartLedsWrite, RGB8, RGBW};
1616
use std::vec;
1717
use std::vec::Vec;
1818

19+
use crate::pixel_order;
20+
use crate::OrderedColors;
21+
1922
/// SPI mode that can be used for this crate
2023
///
2124
/// Provided for convenience
@@ -30,15 +33,17 @@ pub mod devices {
3033
pub struct Sk6812w;
3134
}
3235

33-
pub struct Ws2812<SPI, DEVICE = devices::Ws2812> {
36+
pub struct Ws2812<SPI, DEVICE = devices::Ws2812, PIXELORDER = pixel_order::GRB> {
3437
spi: SPI,
3538
data: Vec<u8>,
36-
device: PhantomData<DEVICE>,
39+
_device: PhantomData<DEVICE>,
40+
_pixel_order: PhantomData<PIXELORDER>,
3741
}
3842

39-
impl<SPI, E> Ws2812<SPI>
43+
impl<SPI, E, PO> Ws2812<SPI, devices::Ws2812, PO>
4044
where
4145
SPI: SpiBus<u8, Error = E>,
46+
PO: OrderedColors,
4247
{
4348
/// Use ws2812 devices via spi
4449
///
@@ -52,7 +57,8 @@ where
5257
Self {
5358
spi,
5459
data,
55-
device: PhantomData {},
60+
_device: PhantomData {},
61+
_pixel_order: PhantomData {},
5662
}
5763
}
5864
}
@@ -75,12 +81,13 @@ where
7581
Self {
7682
spi,
7783
data,
78-
device: PhantomData {},
84+
_device: PhantomData {},
85+
_pixel_order: PhantomData {},
7986
}
8087
}
8188
}
8289

83-
impl<SPI, D, E> Ws2812<SPI, D>
90+
impl<SPI, D, E> Ws2812<SPI, D, PO>
8491
where
8592
SPI: SpiBus<u8, Error = E>,
8693
{
@@ -105,9 +112,10 @@ where
105112
}
106113
}
107114

108-
impl<SPI, E> SmartLedsWrite for Ws2812<SPI>
115+
impl<SPI, E, PO> SmartLedsWrite for Ws2812<SPI, devices::Ws2812, PO>
109116
where
110117
SPI: SpiBus<u8, Error = E>,
118+
PO: OrderedColors,
111119
{
112120
type Error = E;
113121
type Color = RGB8;
@@ -118,10 +126,11 @@ where
118126
I: Into<Self::Color>,
119127
{
120128
for item in iterator {
121-
let item = item.into();
122-
self.write_byte(item.g);
123-
self.write_byte(item.r);
124-
self.write_byte(item.b);
129+
let color: RGB8 = item.into();
130+
let ordered_color = PO::order(color);
131+
self.write_byte(ordered_color[0]);
132+
self.write_byte(ordered_color[1]);
133+
self.write_byte(ordered_color[2]);
125134
}
126135
self.send_data()
127136
}
@@ -141,6 +150,7 @@ where
141150
{
142151
for item in iterator {
143152
let item = item.into();
153+
// SK6812W always expects GRBW order
144154
self.write_byte(item.g);
145155
self.write_byte(item.r);
146156
self.write_byte(item.b);

src/lib.rs

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,51 @@ pub mod devices {
3939
pub struct Sk6812w;
4040
}
4141

42-
pub struct Ws2812<SPI, DEVICE = devices::Ws2812> {
42+
/// The color order the WS2812-like device expects. In most cases, this is GRB
43+
/// and doesn't need to be specified separately.
44+
///
45+
/// For SK6812W devices (with a separate white channel) this is unused
46+
pub mod pixel_order {
47+
pub struct RGB;
48+
pub struct RBG;
49+
pub struct GRB;
50+
pub struct GBR;
51+
pub struct BRG;
52+
pub struct BGR;
53+
}
54+
55+
/// Used to define the pixel order, refer to the pixel_order module
56+
pub trait OrderedColors {
57+
fn order(color: RGB8) -> [u8; 3];
58+
}
59+
60+
macro_rules! impl_ordered_colors {
61+
($struct_name:ident, $r_field:ident, $g_field:ident, $b_field:ident) => {
62+
impl OrderedColors for pixel_order::$struct_name {
63+
fn order(color: RGB8) -> [u8; 3] {
64+
[color.$r_field, color.$g_field, color.$b_field]
65+
}
66+
}
67+
};
68+
}
69+
70+
impl_ordered_colors!(RGB, r, g, b);
71+
impl_ordered_colors!(RBG, r, b, g);
72+
impl_ordered_colors!(GRB, g, r, b);
73+
impl_ordered_colors!(GBR, g, b, r);
74+
impl_ordered_colors!(BRG, b, r, g);
75+
impl_ordered_colors!(BGR, b, g, r);
76+
77+
pub struct Ws2812<SPI, DEVICE = devices::Ws2812, PIXELORDER = pixel_order::GRB> {
4378
spi: SPI,
44-
device: PhantomData<DEVICE>,
79+
_device: PhantomData<DEVICE>,
80+
_pixel_order: PhantomData<PIXELORDER>,
4581
}
4682

47-
impl<SPI, E> Ws2812<SPI>
83+
impl<SPI, E, PO> Ws2812<SPI, devices::Ws2812, PO>
4884
where
4985
SPI: SpiBus<u8, Error = E>,
86+
PO: OrderedColors,
5087
{
5188
/// Use ws2812 devices via spi
5289
///
@@ -59,12 +96,13 @@ where
5996
pub fn new(spi: SPI) -> Self {
6097
Self {
6198
spi,
62-
device: PhantomData {},
99+
_device: PhantomData {},
100+
_pixel_order: PhantomData {},
63101
}
64102
}
65103
}
66104

67-
impl<SPI, E> Ws2812<SPI, devices::Sk6812w>
105+
impl<SPI, E, PO> Ws2812<SPI, devices::Sk6812w, PO>
68106
where
69107
SPI: SpiBus<u8, Error = E>,
70108
{
@@ -81,12 +119,13 @@ where
81119
pub fn new_sk6812w(spi: SPI) -> Self {
82120
Self {
83121
spi,
84-
device: PhantomData {},
122+
_device: PhantomData {},
123+
_pixel_order: PhantomData {},
85124
}
86125
}
87126
}
88127

89-
impl<SPI, D, E> Ws2812<SPI, D>
128+
impl<SPI, D, E, PO> Ws2812<SPI, D, PO>
90129
where
91130
SPI: SpiBus<u8, Error = E>,
92131
{
@@ -113,7 +152,7 @@ where
113152
}
114153
}
115154

116-
impl<SPI, E> SmartLedsWrite for Ws2812<SPI>
155+
impl<SPI, E, PO: OrderedColors> SmartLedsWrite for Ws2812<SPI, devices::Ws2812, PO>
117156
where
118157
SPI: SpiBus<u8, Error = E>,
119158
{
@@ -130,17 +169,18 @@ where
130169
}
131170

132171
for item in iterator {
133-
let item = item.into();
134-
self.write_byte(item.g)?;
135-
self.write_byte(item.r)?;
136-
self.write_byte(item.b)?;
172+
let color: RGB8 = item.into();
173+
let ordered_color = PO::order(color);
174+
self.write_byte(ordered_color[0])?;
175+
self.write_byte(ordered_color[1])?;
176+
self.write_byte(ordered_color[2])?;
137177
}
138178
self.flush()?;
139179
Ok(())
140180
}
141181
}
142182

143-
impl<SPI, E> SmartLedsWrite for Ws2812<SPI, devices::Sk6812w>
183+
impl<SPI, E, PO> SmartLedsWrite for Ws2812<SPI, devices::Sk6812w, PO>
144184
where
145185
SPI: SpiBus<u8, Error = E>,
146186
{
@@ -158,6 +198,7 @@ where
158198

159199
for item in iterator {
160200
let item = item.into();
201+
// SK6812W always expects GRBW order
161202
self.write_byte(item.g)?;
162203
self.write_byte(item.r)?;
163204
self.write_byte(item.b)?;

src/prerendered.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ use core::slice::from_ref;
1212

1313
use smart_leds_trait::{SmartLedsWrite, RGB8, RGBW};
1414

15+
use crate::pixel_order;
16+
use crate::OrderedColors;
17+
1518
/// SPI mode that can be used for this crate
1619
///
1720
/// Provided for convenience
@@ -32,16 +35,18 @@ pub mod devices {
3235
pub struct Sk6812w;
3336
}
3437

35-
pub struct Ws2812<'a, SPI, DEVICE = devices::Ws2812> {
38+
pub struct Ws2812<'a, SPI, DEVICE = devices::Ws2812, PIXELORDER = pixel_order::GRB> {
3639
spi: SPI,
3740
data: &'a mut [u8],
3841
index: usize,
39-
device: PhantomData<DEVICE>,
42+
_device: PhantomData<DEVICE>,
43+
_pixel_order: PhantomData<PIXELORDER>,
4044
}
4145

42-
impl<'a, SPI, E> Ws2812<'a, SPI>
46+
impl<'a, SPI, E, PO> Ws2812<'a, SPI, devices::Ws2812, PO>
4347
where
4448
SPI: SpiBus<u8, Error = E>,
49+
PO: OrderedColors,
4550
{
4651
/// Use ws2812 devices via spi
4752
///
@@ -59,12 +64,13 @@ where
5964
spi,
6065
data,
6166
index: 0,
62-
device: PhantomData {},
67+
_device: PhantomData {},
68+
_pixel_order: PhantomData {},
6369
}
6470
}
6571
}
6672

67-
impl<'a, SPI, E> Ws2812<'a, SPI, devices::Sk6812w>
73+
impl<'a, SPI, E, PO> Ws2812<'a, SPI, devices::Sk6812w, PO>
6874
where
6975
SPI: SpiBus<u8, Error = E>,
7076
{
@@ -87,12 +93,13 @@ where
8793
spi,
8894
data,
8995
index: 0,
90-
device: PhantomData {},
96+
_device: PhantomData {},
97+
_pixel_order: PhantomData {},
9198
}
9299
}
93100
}
94101

95-
impl<'a, SPI, D, E> Ws2812<'a, SPI, D>
102+
impl<SPI, D, E, PO> Ws2812<'_, SPI, D, PO>
96103
where
97104
SPI: SpiBus<u8, Error = E>,
98105
{
@@ -130,9 +137,10 @@ where
130137
}
131138
}
132139

133-
impl<'a, SPI, E> SmartLedsWrite for Ws2812<'a, SPI>
140+
impl<SPI, E, PO> SmartLedsWrite for Ws2812<'_, SPI, devices::Ws2812, PO>
134141
where
135142
SPI: SpiBus<u8, Error = E>,
143+
PO: OrderedColors,
136144
{
137145
type Error = Error<E>;
138146
type Color = RGB8;
@@ -145,16 +153,17 @@ where
145153
self.index = 0;
146154

147155
for item in iterator {
148-
let item = item.into();
149-
self.write_byte(item.g)?;
150-
self.write_byte(item.r)?;
151-
self.write_byte(item.b)?;
156+
let color: RGB8 = item.into();
157+
let ordered_color = PO::order(color);
158+
self.write_byte(ordered_color[0])?;
159+
self.write_byte(ordered_color[1])?;
160+
self.write_byte(ordered_color[2])?;
152161
}
153162
self.send_data().map_err(|e| Error::Spi(e))
154163
}
155164
}
156165

157-
impl<'a, SPI, E> SmartLedsWrite for Ws2812<'a, SPI, devices::Sk6812w>
166+
impl<SPI, E, PO> SmartLedsWrite for Ws2812<'_, SPI, devices::Sk6812w, PO>
158167
where
159168
SPI: SpiBus<u8, Error = E>,
160169
{
@@ -170,6 +179,7 @@ where
170179

171180
for item in iterator {
172181
let item = item.into();
182+
// SK6812W always expects GRBW order
173183
self.write_byte(item.g)?;
174184
self.write_byte(item.r)?;
175185
self.write_byte(item.b)?;

0 commit comments

Comments
 (0)