1#![no_std]
11
12use core::marker::PhantomData;
13use smart_leds_trait::{RGB8, RGBW};
14
15pub mod device {
16 pub struct Ws2812;
17 pub struct Sk6812w;
18
19 pub trait Ws2812Like {
20 type Color: super::EncodeColor;
21 }
22
23 impl Ws2812Like for Ws2812 {
24 type Color = super::RGB8;
25 }
26
27 impl Ws2812Like for Sk6812w {
28 type Color = super::RGBW<u8>;
29 }
30}
31
32pub trait EncodeColor {
33 type Bytes: IntoIterator<Item = u8>;
34 fn encode(self) -> Self::Bytes;
35}
36
37impl EncodeColor for RGB8 {
38 type Bytes = [u8; 3];
39 fn encode(self) -> Self::Bytes {
40 [self.g, self.r, self.b]
41 }
42}
43
44impl EncodeColor for RGBW<u8> {
45 type Bytes = [u8; 4];
46 fn encode(self) -> Self::Bytes {
47 [self.g, self.r, self.b, self.a.0]
48 }
49}
50
51pub struct Ws2812<UART, DEV = device::Ws2812> {
52 uart: UART,
53 _device: PhantomData<DEV>,
54}
55
56fn encode_byte(mut byte: u8) -> [u8; 4] {
58 let mut res = [0; 4];
59 for i in 0..4 {
60 res[i] = !(0b_0001_0000
61 | if (byte & 0b_10_00_0000) != 0 {
62 0b_0000_0011
63 } else {
64 0
65 }
66 | if (byte & 0b_01_00_0000) != 0 {
67 0b_0110_0000
68 } else {
69 0
70 });
71 byte <<= 2;
72 }
73 res
74}
75
76impl<UART, DEV> Ws2812<UART, DEV> {
77 pub fn new(uart: UART) -> Self {
79 Self {
80 uart,
81 _device: PhantomData,
82 }
83 }
84}
85
86#[cfg(feature = "blocking")]
87mod blocking {
88 use super::{device, encode_byte, EncodeColor, Ws2812};
89 use embedded_io::{ErrorType as BlockingErrorType, Write as BlockingWrite};
90 use smart_leds_trait::SmartLedsWrite;
91
92 impl<UART, DEV> Ws2812<UART, DEV>
93 where
94 UART: BlockingWrite,
95 {
96 fn send_byte(&mut self, byte: u8) -> Result<(), <UART as BlockingErrorType>::Error> {
97 let bytes = encode_byte(byte);
98 self.uart.write_all(&bytes)
99 }
100 }
101
102 impl<UART, DEV> SmartLedsWrite for Ws2812<UART, DEV>
103 where
104 UART: BlockingWrite,
105 DEV: device::Ws2812Like,
106 {
107 type Error = <UART as BlockingErrorType>::Error;
108 type Color = DEV::Color;
109
110 fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error>
111 where
112 T: IntoIterator<Item = I>,
113 I: Into<Self::Color>,
114 {
115 for item in iterator {
116 let color = item.into();
117 for byte in color.encode() {
118 self.send_byte(byte)?;
119 }
120 }
121 Ok(())
122 }
123 }
124}
125
126#[cfg(feature = "async")]
127mod asyncs {
128 use super::{device, encode_byte, EncodeColor, Ws2812};
129 use embedded_io_async::{ErrorType as AsyncErrorType, Write as AsyncWrite};
130 use smart_leds_trait::SmartLedsWriteAsync;
131
132 impl<UART, DEV> Ws2812<UART, DEV>
133 where
134 UART: AsyncWrite,
135 {
136 async fn send_byte_async(
137 &mut self,
138 byte: u8,
139 ) -> Result<(), <UART as AsyncErrorType>::Error> {
140 let bytes = encode_byte(byte);
141 self.uart.write_all(&bytes).await
142 }
143 }
144
145 impl<UART, DEV> SmartLedsWriteAsync for Ws2812<UART, DEV>
146 where
147 UART: AsyncWrite,
148 DEV: device::Ws2812Like,
149 {
150 type Error = <UART as AsyncErrorType>::Error;
151 type Color = DEV::Color;
152
153 async fn write<T, I>(&mut self, iterator: T) -> Result<(), Self::Error>
154 where
155 T: IntoIterator<Item = I>,
156 I: Into<Self::Color>,
157 {
158 for item in iterator {
159 let color = item.into();
160 for byte in color.encode() {
161 self.send_byte_async(byte).await?;
162 }
163 }
164 Ok(())
165 }
166 }
167}