1#![no_std]
51#![forbid(unsafe_code)]
52#![forbid(missing_docs)]
53
54use embedded_hal::blocking::i2c::{Write, WriteRead};
58
59#[repr(u8)]
60#[derive(Clone, Copy, Debug)]
61enum Register {
62 DeviceId = 0x00,
63 FirmwareMinor = 0x01,
64 ButtonStatus = 0x03,
65 InterruptConfig = 0x04,
66 ButtonDebounceTime = 0x05,
67 PressedQueueStatus = 0x07,
68 PressedQueueFront = 0x08,
69 PressedQueueBack = 0x0C,
70 ClickedQueueStatus = 0x10,
71 ClickedQueueFront = 0x11,
72 ClickedQueueBack = 0x15,
73 LedBrightness = 0x19,
74 LedPulseGranularity = 0x1A,
75 LedPulseCycleTime = 0x1B,
76 LedPulseOffTime = 0x1D,
77 I2CAddress = 0x1F,
78}
79
80#[derive(Debug)]
82pub enum Error {
83 I2C,
86 QwiicButton(QwiicButtonError),
88}
89
90#[derive(Debug)]
92pub enum QwiicButtonError {
93 AddressError,
96}
97
98#[derive(Debug)]
100pub struct ButtonLED<I2C> {
101 i2c: I2C,
102 address: u8,
103}
104
105#[derive(Debug)]
107pub struct ButtonStatus {
108 pub event_available: bool,
110 pub clicked: bool,
112 pub pressed: bool,
114}
115
116impl From<u8> for ButtonStatus {
117 fn from(val: u8) -> Self {
118 ButtonStatus {
119 event_available: 0b1 & val == 1,
120 clicked: 0b10 & val == 2,
121 pressed: 0b100 & val == 4,
122 }
123 }
124}
125
126impl From<ButtonStatus> for u8 {
127 fn from(val: ButtonStatus) -> u8 {
128 (val.event_available as u8 & 0b1)
129 | (val.clicked as u8 & 0b1) << 1
130 | (val.pressed as u8 & 0b1) << 2
131 }
132}
133
134#[derive(Debug)]
136pub struct InterruptConfig {
137 pub pressed: bool,
139 pub clicked: bool,
141}
142
143impl From<u8> for InterruptConfig {
144 fn from(val: u8) -> Self {
145 InterruptConfig {
146 pressed: 0b01 & val == 1,
147 clicked: 0b10 & val == 2,
148 }
149 }
150}
151
152impl From<InterruptConfig> for u8 {
153 fn from(val: InterruptConfig) -> u8 {
154 (val.clicked as u8 & 0b1) << 1 | (val.pressed as u8 & 0b1)
155 }
156}
157
158#[derive(Debug)]
160pub struct PressedQueueStatus {
161 pub buffer_empty: bool,
163 pub buffer_full: bool,
165}
166
167impl From<u8> for PressedQueueStatus {
168 fn from(val: u8) -> Self {
169 PressedQueueStatus {
170 buffer_empty: 0b010 & val == 2,
171 buffer_full: 0b100 & val == 4,
172 }
173 }
174}
175
176#[derive(Debug)]
178pub struct ClickedQueueStatus {
179 pub buffer_empty: bool,
181 pub buffer_full: bool,
183}
184
185impl From<u8> for ClickedQueueStatus {
186 fn from(val: u8) -> Self {
187 ClickedQueueStatus {
188 buffer_empty: 0b010 & val == 2,
189 buffer_full: 0b100 & val == 4,
190 }
191 }
192}
193
194const ADDRESS_MIN: u8 = 0x08;
195const ADDRESS_MAX: u8 = 0x77;
196
197impl<I2C> ButtonLED<I2C>
198where
199 I2C: Write + WriteRead,
200{
201 fn write_u8(&mut self, op: Register, payload: u8) -> Result<(), Error> {
202 self.i2c
203 .write(self.address, &[op as u8, payload])
204 .map_err(|_| Error::I2C)
205 }
206
207 fn read_u8(&mut self, op: Register) -> Result<u8, Error> {
208 let mut buf: [u8; 1] = [0u8; 1];
209 match self.i2c.write_read(self.address, &[op as u8], &mut buf) {
210 Ok(_) => Ok(buf[0]),
211 Err(_) => Err(Error::I2C),
212 }
213 }
214
215 fn write_u16(&mut self, op: Register, payload: u16) -> Result<(), Error> {
216 let mut cmd: [u8; 3] = [0u8; 3];
217 cmd[0] = op as u8;
218 cmd[1..].copy_from_slice(&payload.to_le_bytes());
219 self.i2c.write(self.address, &cmd).map_err(|_| Error::I2C)
220 }
221
222 fn read_u16(&mut self, op: Register) -> Result<u16, Error> {
223 let mut buf: [u8; 2] = [0u8; 2];
224 match self.i2c.write_read(self.address, &[op as u8], &mut buf) {
225 Ok(_) => Ok(u16::from_le_bytes(buf)),
226 Err(_) => Err(Error::I2C),
227 }
228 }
229
230 fn read_u32(&mut self, op: Register) -> Result<u32, Error> {
231 let mut buf: [u8; 4] = [0u8; 4];
232 match self.i2c.write_read(self.address, &[op as u8], &mut buf) {
233 Ok(_) => Ok(u32::from_le_bytes(buf)),
234 Err(_) => Err(Error::I2C),
235 }
236 }
237
238 pub fn init(i2c: I2C, address: u8) -> Self {
240 Self { i2c, address }
241 }
242
243 pub fn button_id(&mut self) -> Result<u8, Error> {
245 self.read_u8(Register::DeviceId)
246 }
247
248 pub fn firmware_version(&mut self) -> Result<u16, Error> {
250 self.read_u16(Register::FirmwareMinor)
251 }
252
253 pub fn button_status(&mut self) -> Result<ButtonStatus, Error> {
255 self.read_u8(Register::ButtonStatus).map(|r| r.into())
256 }
257
258 pub fn set_button_status(&mut self, new_status: ButtonStatus) -> Result<(), Error> {
260 self.write_u8(Register::ButtonStatus, new_status.into())
261 }
262
263 pub fn interrupt_config(&mut self) -> Result<InterruptConfig, Error> {
265 self.read_u8(Register::InterruptConfig).map(|r| r.into())
266 }
267
268 pub fn set_interrupt_config(&mut self, config: InterruptConfig) -> Result<(), Error> {
270 self.write_u8(Register::InterruptConfig, config.into())
271 }
272
273 pub fn button_debounce_time(&mut self) -> Result<u16, Error> {
276 self.read_u16(Register::ButtonDebounceTime)
277 }
278
279 pub fn set_button_debounce_time(&mut self, time: u16) -> Result<(), Error> {
281 self.write_u16(Register::ButtonDebounceTime, time)
282 }
283
284 pub fn pressed_queue_full(&mut self) -> Result<bool, Error> {
286 self.read_u8(Register::PressedQueueStatus)
287 .map(|r| r & 0b100 == 4)
288 }
289
290 pub fn pressed_queue_empty(&mut self) -> Result<bool, Error> {
292 self.read_u8(Register::PressedQueueStatus)
293 .map(|r| r & 0b010 == 2)
294 }
295
296 pub fn pressed_queue_status(&mut self) -> Result<PressedQueueStatus, Error> {
298 self.read_u8(Register::PressedQueueStatus).map(|r| r.into())
299 }
300
301 pub fn newest_press_timestamp(&mut self) -> Result<u32, Error> {
303 let stamp = self.read_u32(Register::PressedQueueFront)?;
304 let mut current_status = self.read_u8(Register::PressedQueueStatus)?;
305 current_status |= 1;
306 self.write_u8(Register::PressedQueueStatus, current_status)?;
307 Ok(stamp)
308 }
309
310 pub fn oldest_press_timestamp(&mut self) -> Result<u32, Error> {
312 let stamp = self.read_u32(Register::PressedQueueBack)?;
313 let mut current_status = self.read_u8(Register::PressedQueueStatus)?;
314 current_status |= 1;
315 self.write_u8(Register::PressedQueueStatus, current_status)?;
316 Ok(stamp)
317 }
318
319 pub fn clicked_queue_full(&mut self) -> Result<bool, Error> {
321 self.read_u8(Register::ClickedQueueStatus)
322 .map(|r| r & 0b100 == 4)
323 }
324
325 pub fn clicked_queue_empty(&mut self) -> Result<bool, Error> {
327 self.read_u8(Register::ClickedQueueStatus)
328 .map(|r| r & 0b010 == 2)
329 }
330
331 pub fn clicked_queue_status(&mut self) -> Result<ClickedQueueStatus, Error> {
333 self.read_u8(Register::ClickedQueueStatus).map(|r| r.into())
334 }
335
336 pub fn newest_click_timestamp(&mut self) -> Result<u32, Error> {
338 let stamp = self.read_u32(Register::ClickedQueueFront)?;
339 let mut current_status = self.read_u8(Register::ClickedQueueStatus)?;
340 current_status |= 1;
341 self.write_u8(Register::ClickedQueueStatus, current_status)?;
342 Ok(stamp)
343 }
344
345 pub fn oldest_click_timestamp(&mut self) -> Result<u32, Error> {
347 let stamp = self.read_u32(Register::ClickedQueueBack)?;
348 let mut current_status = self.read_u8(Register::ClickedQueueStatus)?;
349 current_status |= 1;
350 self.write_u8(Register::ClickedQueueStatus, current_status)?;
351 Ok(stamp)
352 }
353
354 pub fn led_brightness(&mut self) -> Result<u8, Error> {
356 self.read_u8(Register::LedBrightness)
357 }
358
359 pub fn set_led_brightness(&mut self, brightness: u8) -> Result<(), Error> {
361 self.write_u8(Register::LedBrightness, brightness)
362 }
363
364 pub fn led_pulse_granularity(&mut self) -> Result<u8, Error> {
366 self.read_u8(Register::LedPulseGranularity)
367 }
368
369 pub fn set_led_pulse_granularity(&mut self, brightness: u8) -> Result<(), Error> {
371 self.write_u8(Register::LedPulseGranularity, brightness)
372 }
373
374 pub fn led_pulse_cycle_time(&mut self) -> Result<u16, Error> {
376 self.read_u16(Register::LedPulseCycleTime)
377 }
378
379 pub fn set_led_pulse_cycle_time(&mut self, cycle_time: u16) -> Result<(), Error> {
381 self.write_u16(Register::LedPulseCycleTime, cycle_time)
382 }
383
384 pub fn led_pulse_off_time(&mut self) -> Result<u16, Error> {
386 self.read_u16(Register::LedPulseOffTime)
387 }
388
389 pub fn set_led_pulse_off_time(&mut self, off_time: u16) -> Result<(), Error> {
391 self.write_u16(Register::LedPulseOffTime, off_time)
392 }
393
394 pub fn device_address(&mut self) -> Result<u8, Error> {
396 self.read_u8(Register::I2CAddress)
397 }
398
399 pub fn set_device_address(&mut self, new_address: u8) -> Result<(), Error> {
401 if !(ADDRESS_MIN..=ADDRESS_MAX).contains(&new_address) {
402 return Err(Error::QwiicButton(QwiicButtonError::AddressError));
403 }
404 match self.write_u8(Register::I2CAddress, new_address) {
405 Ok(_) => {
406 self.address = new_address;
407 Ok(())
408 }
409 Err(e) => Err(e),
410 }
411 }
412}