1use crate::{addresses, Color, Error, I2cDevice, Result};
6use embedded_hal::i2c::I2c;
7
8pub const NUM_LEDS: usize = 8;
10
11pub struct Pixels<I2C> {
34 device: I2cDevice<I2C>,
35 data: [u8; NUM_LEDS * 4],
36}
37
38impl<I2C, E> Pixels<I2C>
39where
40 I2C: I2c<Error = E>,
41{
42 pub fn new(i2c: I2C) -> Result<Self, E> {
44 Self::new_with_address(i2c, addresses::PIXELS)
45 }
46
47 pub fn new_with_address(i2c: I2C, address: u8) -> Result<Self, E> {
49 let mut pixels = Self {
50 device: I2cDevice::new(i2c, address),
51 data: [0xE0; NUM_LEDS * 4], };
53
54 pixels.clear_all();
56
57 Ok(pixels)
58 }
59
60 pub fn address(&self) -> u8 {
62 self.device.address
63 }
64
65 fn map_brightness(brightness: u8) -> u8 {
67 let clamped = if brightness > 100 { 100 } else { brightness };
68 ((clamped as u16 * 31) / 100) as u8
69 }
70
71 pub fn set_color(
79 &mut self,
80 index: usize,
81 color: Color,
82 brightness: u8,
83 ) -> Result<&mut Self, E> {
84 if index >= NUM_LEDS {
85 return Err(Error::OutOfRange);
86 }
87
88 let byte_index = index * 4;
89 let mapped_brightness = Self::map_brightness(brightness);
90 let color_data = color.to_apa102_data() | (mapped_brightness as u32) | 0xE0;
91
92 let bytes = color_data.to_le_bytes();
93 self.data[byte_index..byte_index + 4].copy_from_slice(&bytes);
94
95 Ok(self)
96 }
97
98 pub fn set_rgb(
108 &mut self,
109 index: usize,
110 r: u8,
111 g: u8,
112 b: u8,
113 brightness: u8,
114 ) -> Result<&mut Self, E> {
115 self.set_color(index, Color::new(r, g, b), brightness)
116 }
117
118 pub fn set_brightness(&mut self, index: usize, brightness: u8) -> Result<&mut Self, E> {
125 if index >= NUM_LEDS {
126 return Err(Error::OutOfRange);
127 }
128
129 let byte_index = index * 4;
130 let mapped_brightness = Self::map_brightness(brightness);
131 self.data[byte_index] = mapped_brightness | 0xE0;
132
133 Ok(self)
134 }
135
136 pub fn set_all_color(&mut self, color: Color, brightness: u8) -> &mut Self {
138 for i in 0..NUM_LEDS {
139 let _ = self.set_color(i, color, brightness);
140 }
141 self
142 }
143
144 pub fn set_all_rgb(&mut self, r: u8, g: u8, b: u8, brightness: u8) -> &mut Self {
146 self.set_all_color(Color::new(r, g, b), brightness)
147 }
148
149 pub fn set_range_color(
158 &mut self,
159 from: usize,
160 to: usize,
161 color: Color,
162 brightness: u8,
163 ) -> &mut Self {
164 let end = if to >= NUM_LEDS { NUM_LEDS - 1 } else { to };
165 for i in from..=end {
166 let _ = self.set_color(i, color, brightness);
167 }
168 self
169 }
170
171 pub fn set_all_brightness(&mut self, brightness: u8) -> &mut Self {
173 for i in 0..NUM_LEDS {
174 let _ = self.set_brightness(i, brightness);
175 }
176 self
177 }
178
179 pub fn clear(&mut self, index: usize) -> Result<&mut Self, E> {
181 self.set_color(index, Color::BLACK, 0)
182 }
183
184 pub fn clear_range(&mut self, from: usize, to: usize) -> &mut Self {
186 let end = if to >= NUM_LEDS { NUM_LEDS - 1 } else { to };
187 for i in from..=end {
188 let _ = self.clear(i);
189 }
190 self
191 }
192
193 pub fn clear_all(&mut self) -> &mut Self {
195 for i in 0..NUM_LEDS {
196 let _ = self.set_color(i, Color::BLACK, 0);
200 }
201 self
202 }
203
204 pub fn show(&mut self) -> Result<(), E> {
208 self.device.write(&self.data)?;
209 Ok(())
210 }
211
212 pub fn set_color_show(&mut self, index: usize, color: Color, brightness: u8) -> Result<(), E> {
214 self.set_color(index, color, brightness)?;
215 self.show()
216 }
217
218 pub fn release(self) -> I2C {
220 self.device.release()
221 }
222}