adafruit_seesaw/modules/
neopixel.rs1use super::{Modules, Reg};
2use crate::{devices::SeesawDevice, driver::Driver, DriverExt, SeesawError};
3use rgb::ComponentSlice;
4
5const SET_PIN: &Reg = &[Modules::Neopixel.into_u8(), 0x01];
9const SET_SPEED: &Reg = &[Modules::Neopixel.into_u8(), 0x02];
12const SET_LEN: &Reg = &[Modules::Neopixel.into_u8(), 0x03];
16const SET_BUF: &Reg = &[Modules::Neopixel.into_u8(), 0x04];
21const SHOW: &Reg = &[Modules::Neopixel.into_u8(), 0x05];
25
26pub trait NeopixelModule<D: Driver>: SeesawDevice<Driver = D> {
27 const C_SIZE: usize = {
29 match core::mem::size_of::<Self::Color>() {
30 3 => 3,
31 4 => 4,
32 _ => panic!("Invalid color size"),
33 }
34 };
35 const N_LEDS: usize = 1;
37 const PIN: u8;
39
40 type Color: ComponentSlice<u8>;
41
42 fn enable_neopixel(&mut self) -> Result<(), SeesawError<D::Error>> {
45 let addr = self.addr();
46
47 self.driver()
48 .write_u8(addr, SET_PIN, Self::PIN)
49 .map(|_| self.driver().delay_us(10_000))
50 .and_then(|_| {
51 self.driver()
52 .write_u16(addr, SET_LEN, (Self::C_SIZE * Self::N_LEDS) as u16)
53 })
54 .map(|_| self.driver().delay_us(10_000))
55 .map_err(SeesawError::I2c)
56 }
57
58 fn set_neopixel_speed(&mut self, speed: NeopixelSpeed) -> Result<(), SeesawError<D::Error>> {
59 let addr = self.addr();
60
61 self.driver()
62 .write_u8(
63 addr,
64 SET_SPEED,
65 match speed {
66 NeopixelSpeed::Khz400 => 0,
67 NeopixelSpeed::Khz800 => 1,
68 },
69 )
70 .map(|_| self.driver().delay_us(10_000))
71 .map_err(SeesawError::I2c)
72 }
73
74 fn set_neopixel_color(&mut self, color: Self::Color) -> Result<(), SeesawError<D::Error>>
77 where
78 [(); 2 + Self::C_SIZE]: Sized,
79 {
80 self.set_nth_neopixel_color(0, color)
81 }
82
83 fn set_nth_neopixel_color(
85 &mut self,
86 n: usize,
87 color: Self::Color,
88 ) -> Result<(), SeesawError<D::Error>>
89 where
90 [(); 2 + Self::C_SIZE]: Sized,
91 {
92 assert!(n < Self::N_LEDS);
93 let addr = self.addr();
94 let mut buf = [0; 2 + Self::C_SIZE];
95 buf[..2].copy_from_slice(&u16::to_be_bytes((Self::C_SIZE * n) as u16));
96 buf[2..].copy_from_slice(color.as_slice());
97 self.driver()
98 .register_write(addr, SET_BUF, &buf)
99 .map_err(SeesawError::I2c)
100 }
101
102 fn set_neopixel_colors(
110 &mut self,
111 colors: &[Self::Color; Self::N_LEDS],
112 ) -> Result<(), SeesawError<D::Error>>
113 where
114 [(); 2 + color_bytes_per_write(Self::C_SIZE)]: Sized,
115 {
116 let mut buf = [0; 2 + color_bytes_per_write(Self::C_SIZE)];
117 let addr = self.addr();
118
119 colors
120 .chunks(max_colors_per_write(Self::C_SIZE))
121 .enumerate()
122 .try_for_each(|(i, chunk)| {
123 let offset = u16::to_be_bytes(
124 (Self::C_SIZE * i * max_colors_per_write(Self::C_SIZE)) as u16,
125 );
126 buf[..2].copy_from_slice(&offset);
127 chunk.iter().enumerate().for_each(|(j, c)| {
128 let start = 2 + (j * Self::C_SIZE);
129 buf[start..start + Self::C_SIZE].copy_from_slice(c.as_slice());
130 });
131
132 self.driver().register_write(
133 addr,
134 SET_BUF,
135 &buf[0..2 + (Self::C_SIZE * chunk.len())],
136 )
137 })
138 .map_err(SeesawError::I2c)
139 }
140
141 fn sync_neopixel(&mut self) -> Result<(), SeesawError<D::Error>> {
142 let addr = self.addr();
143
144 self.driver()
145 .register_write(addr, SHOW, &[])
146 .map(|_| self.driver().delay_us(125))
147 .map_err(SeesawError::I2c)
148 }
149}
150
151pub const fn max_colors_per_write(c_size: usize) -> usize {
154 match c_size {
155 3 => 9, 4 => 7, _ => 1, }
159}
160
161pub const fn color_bytes_per_write(c_size: usize) -> usize {
164 c_size * max_colors_per_write(c_size)
165}
166
167#[derive(Debug, Default)]
169#[cfg_attr(feature = "defmt", derive(defmt::Format))]
170pub enum NeopixelSpeed {
171 Khz400 = 0,
172 #[default]
173 Khz800 = 1,
174}