@@ -8,10 +8,11 @@ use embedded_hal as hal;
8
8
use hal:: spi:: { Mode , Phase , Polarity , SpiBus } ;
9
9
10
10
use core:: marker:: PhantomData ;
11
- use core:: slice:: from_ref;
12
11
13
12
use smart_leds_trait:: { SmartLedsWrite , RGB8 , RGBW } ;
14
13
14
+ const RESET_DATA_LEN : usize = 140 ;
15
+
15
16
/// SPI mode that can be used for this crate
16
17
///
17
18
/// Provided for convenience
@@ -43,16 +44,19 @@ impl<'a, SPI, E> Ws2812<'a, SPI>
43
44
where
44
45
SPI : SpiBus < u8 , Error = E > ,
45
46
{
46
- /// Use ws2812 devices via spi
47
+ /// Use WS2812 devices via SPI
47
48
///
48
49
/// The SPI bus should run within 2 MHz to 3.8 MHz
49
50
///
50
- /// You may need to look at the datasheet and your own hal to verify this.
51
+ /// You may need to look at the datasheet and your own HAL to verify this.
51
52
///
52
- /// You need to provide a buffer `data`, whoose length is at least 12 * the
53
- /// length of the led strip + 20 byes (or 40, if using the `mosi_idle_high` feature)
53
+ /// You need to provide a buffer `data`, whose length is at least 12 * the
54
+ /// length of the led strip
55
+ /// - + 140 bytes if using the `reset_single_transaction` feature
56
+ /// - + 140 bytes if using the `mosi_idle_high` feature
57
+ /// - + 280 bytes if using the `mosi_idle_high` and `reset_single_transaction` features
54
58
///
55
- /// Please ensure that the mcu is pretty fast, otherwise weird timing
59
+ /// Please ensure that the MCU is pretty fast, otherwise weird timing
56
60
/// issues will occur
57
61
pub fn new ( spi : SPI , data : & ' a mut [ u8 ] ) -> Self {
58
62
Self {
@@ -68,18 +72,21 @@ impl<'a, SPI, E> Ws2812<'a, SPI, devices::Sk6812w>
68
72
where
69
73
SPI : SpiBus < u8 , Error = E > ,
70
74
{
71
- /// Use sk6812w devices via spi
75
+ /// Use SK6812W devices via SPI
72
76
///
73
77
/// The SPI bus should run within 2.3 MHz to 3.8 MHz at least.
74
78
///
75
- /// You may need to look at the datasheet and your own hal to verify this.
79
+ /// You may need to look at the datasheet and your own HAL to verify this.
76
80
///
77
- /// You need to provide a buffer `data`, whoose length is at least 12 * the
81
+ /// You need to provide a buffer `data`, whose length is at least 16 * the
78
82
/// length of the led strip
83
+ /// - + 140 bytes if using the `reset_single_transaction` feature
84
+ /// - + 140 bytes if using the `mosi_idle_high` feature
85
+ /// - + 280 bytes if using the `mosi_idle_high` and `reset_single_transaction` features
79
86
///
80
- /// Please ensure that the mcu is pretty fast, otherwise weird timing
87
+ /// Please ensure that the MCU is pretty fast, otherwise weird timing
81
88
/// issues will occur
82
- // The spi frequencies are just the limits, the available timing data isn't
89
+ // The SPI frequencies are just the limits, the available timing data isn't
83
90
// complete
84
91
pub fn new_sk6812w ( spi : SPI , data : & ' a mut [ u8 ] ) -> Self {
85
92
Self {
@@ -95,7 +102,7 @@ impl<'a, SPI, D, E> Ws2812<'a, SPI, D>
95
102
where
96
103
SPI : SpiBus < u8 , Error = E > ,
97
104
{
98
- /// Write a single byte for ws2812 devices
105
+ /// Write a single byte for WS2812-like devices
99
106
fn write_byte ( & mut self , mut data : u8 ) -> Result < ( ) , Error < E > > {
100
107
// Send two bits in one spi byte. High time first, then the low time
101
108
// The maximum for T0H is 500ns, the minimum for one bit 1063 ns.
@@ -114,19 +121,31 @@ where
114
121
Ok ( ( ) )
115
122
}
116
123
117
- fn send_data ( & mut self ) -> Result < ( ) , E > {
118
- if cfg ! ( feature = "mosi_idle_high" ) {
119
- for _ in 0 ..140 {
120
- self . spi . write ( from_ref ( & 0 ) ) ?;
121
- }
124
+ /// Add a reset sequence (140 zeroes) to the data buffer
125
+ // Is always used for `mosi_idle_high`, as otherwise the time required to fill the buffer can lead to idle cycles on the SPI bus
126
+ fn write_reset ( & mut self ) -> Result < ( ) , Error < E > > {
127
+ if self . index + RESET_DATA_LEN > self . data . len ( ) {
128
+ return Err ( Error :: OutOfBounds ) ;
129
+ }
130
+ for _ in 0 ..RESET_DATA_LEN {
131
+ self . data [ self . index ] = 0 ;
132
+ self . index += 1 ;
122
133
}
134
+ Ok ( ( ) )
135
+ }
123
136
124
- self . spi . write ( & self . data [ ..self . index ] ) ?;
125
- for _ in 0 ..140 {
126
- self . spi . write ( from_ref ( & 0 ) ) ?;
137
+ /// Send a reset sequence (140 zeroes) on the bus
138
+ fn send_reset ( & mut self ) -> Result < ( ) , Error < E > > {
139
+ for _ in 0 ..RESET_DATA_LEN {
140
+ self . spi . write ( & [ 0 ] ) . map_err ( Error :: Spi ) ?;
127
141
}
142
+
128
143
Ok ( ( ) )
129
144
}
145
+
146
+ fn send_data ( & mut self ) -> Result < ( ) , E > {
147
+ self . spi . write ( & self . data [ ..self . index ] )
148
+ }
130
149
}
131
150
132
151
impl < ' a , SPI , E > SmartLedsWrite for Ws2812 < ' a , SPI >
@@ -135,21 +154,35 @@ where
135
154
{
136
155
type Error = Error < E > ;
137
156
type Color = RGB8 ;
138
- /// Write all the items of an iterator to a ws2812 strip
157
+ /// Write all the items of an iterator to a WS2812 strip
139
158
fn write < T , I > ( & mut self , iterator : T ) -> Result < ( ) , Error < E > >
140
159
where
141
160
T : IntoIterator < Item = I > ,
142
161
I : Into < Self :: Color > ,
143
162
{
144
163
self . index = 0 ;
145
164
165
+ if cfg ! ( feature = "mosi_idle_high" ) {
166
+ self . write_reset ( ) ?;
167
+ }
168
+
146
169
for item in iterator {
147
170
let item = item. into ( ) ;
148
171
self . write_byte ( item. g ) ?;
149
172
self . write_byte ( item. r ) ?;
150
173
self . write_byte ( item. b ) ?;
151
174
}
152
- self . send_data ( ) . map_err ( |e| Error :: Spi ( e) )
175
+
176
+ if cfg ! ( feature = "reset_single_transaction" ) {
177
+ self . write_reset ( ) ?;
178
+ }
179
+
180
+ self . send_data ( ) . map_err ( Error :: Spi ) ?;
181
+
182
+ if !cfg ! ( feature = "reset_single_transaction" ) {
183
+ self . send_reset ( ) ?;
184
+ }
185
+ Ok ( ( ) )
153
186
}
154
187
}
155
188
@@ -159,21 +192,35 @@ where
159
192
{
160
193
type Error = Error < E > ;
161
194
type Color = RGBW < u8 , u8 > ;
162
- /// Write all the items of an iterator to a ws2812 strip
195
+ /// Write all the items of an iterator to a SK6812W strip
163
196
fn write < T , I > ( & mut self , iterator : T ) -> Result < ( ) , Error < E > >
164
197
where
165
198
T : IntoIterator < Item = I > ,
166
199
I : Into < Self :: Color > ,
167
200
{
168
201
self . index = 0 ;
169
202
203
+ if cfg ! ( feature = "mosi_idle_high" ) {
204
+ self . write_reset ( ) ?;
205
+ }
206
+
170
207
for item in iterator {
171
208
let item = item. into ( ) ;
172
209
self . write_byte ( item. g ) ?;
173
210
self . write_byte ( item. r ) ?;
174
211
self . write_byte ( item. b ) ?;
175
212
self . write_byte ( item. a . 0 ) ?;
176
213
}
177
- self . send_data ( ) . map_err ( |e| Error :: Spi ( e) )
214
+
215
+ if cfg ! ( feature = "reset_single_transaction" ) {
216
+ self . write_reset ( ) ?;
217
+ }
218
+
219
+ self . send_data ( ) . map_err ( Error :: Spi ) ?;
220
+
221
+ if !cfg ! ( feature = "reset_single_transaction" ) {
222
+ self . send_reset ( ) ?;
223
+ }
224
+ Ok ( ( ) )
178
225
}
179
226
}
0 commit comments