Skip to content

Commit ae413e9

Browse files
Add pixel order functionality
Should be backwards compatible
1 parent 6c8edbb commit ae413e9

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.reset()?;
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
@@ -13,6 +13,9 @@ use smart_leds_trait::{SmartLedsWrite, RGB8, RGBW};
1313

1414
const RESET_DATA_LEN: usize = 140;
1515

16+
use crate::pixel_order;
17+
use crate::OrderedColors;
18+
1619
/// SPI mode that can be used for this crate
1720
///
1821
/// Provided for convenience
@@ -33,16 +36,18 @@ pub mod devices {
3336
pub struct Sk6812w;
3437
}
3538

36-
pub struct Ws2812<'a, SPI, DEVICE = devices::Ws2812> {
39+
pub struct Ws2812<'a, SPI, DEVICE = devices::Ws2812, PIXELORDER = pixel_order::GRB> {
3740
spi: SPI,
3841
data: &'a mut [u8],
3942
index: usize,
40-
device: PhantomData<DEVICE>,
43+
_device: PhantomData<DEVICE>,
44+
_pixel_order: PhantomData<PIXELORDER>,
4145
}
4246

43-
impl<'a, SPI, E> Ws2812<'a, SPI>
47+
impl<'a, SPI, E, PO> Ws2812<'a, SPI, devices::Ws2812, PO>
4448
where
4549
SPI: SpiBus<u8, Error = E>,
50+
PO: OrderedColors,
4651
{
4752
/// Use WS2812 devices via SPI
4853
///
@@ -63,12 +68,13 @@ where
6368
spi,
6469
data,
6570
index: 0,
66-
device: PhantomData {},
71+
_device: PhantomData {},
72+
_pixel_order: PhantomData {},
6773
}
6874
}
6975
}
7076

71-
impl<'a, SPI, E> Ws2812<'a, SPI, devices::Sk6812w>
77+
impl<'a, SPI, E, PO> Ws2812<'a, SPI, devices::Sk6812w, PO>
7278
where
7379
SPI: SpiBus<u8, Error = E>,
7480
{
@@ -93,12 +99,13 @@ where
9399
spi,
94100
data,
95101
index: 0,
96-
device: PhantomData {},
102+
_device: PhantomData {},
103+
_pixel_order: PhantomData {},
97104
}
98105
}
99106
}
100107

101-
impl<'a, SPI, D, E> Ws2812<'a, SPI, D>
108+
impl<SPI, D, E, PO> Ws2812<'_, SPI, D, PO>
102109
where
103110
SPI: SpiBus<u8, Error = E>,
104111
{
@@ -148,9 +155,10 @@ where
148155
}
149156
}
150157

151-
impl<'a, SPI, E> SmartLedsWrite for Ws2812<'a, SPI>
158+
impl<SPI, E, PO> SmartLedsWrite for Ws2812<'_, SPI, devices::Ws2812, PO>
152159
where
153160
SPI: SpiBus<u8, Error = E>,
161+
PO: OrderedColors,
154162
{
155163
type Error = Error<E>;
156164
type Color = RGB8;
@@ -167,10 +175,11 @@ where
167175
}
168176

169177
for item in iterator {
170-
let item = item.into();
171-
self.write_byte(item.g)?;
172-
self.write_byte(item.r)?;
173-
self.write_byte(item.b)?;
178+
let color: RGB8 = item.into();
179+
let ordered_color = PO::order(color);
180+
self.write_byte(ordered_color[0])?;
181+
self.write_byte(ordered_color[1])?;
182+
self.write_byte(ordered_color[2])?;
174183
}
175184

176185
if cfg!(feature = "reset_single_transaction") {
@@ -186,7 +195,7 @@ where
186195
}
187196
}
188197

189-
impl<'a, SPI, E> SmartLedsWrite for Ws2812<'a, SPI, devices::Sk6812w>
198+
impl<SPI, E, PO> SmartLedsWrite for Ws2812<'_, SPI, devices::Sk6812w, PO>
190199
where
191200
SPI: SpiBus<u8, Error = E>,
192201
{
@@ -206,6 +215,7 @@ where
206215

207216
for item in iterator {
208217
let item = item.into();
218+
// SK6812W always expects GRBW order
209219
self.write_byte(item.g)?;
210220
self.write_byte(item.r)?;
211221
self.write_byte(item.b)?;

0 commit comments

Comments
 (0)