use crate::{addresses, Error, I2cDevice, Result};
use embedded_hal::i2c::I2c;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ButtonState {
pub a: bool,
pub b: bool,
pub c: bool,
}
impl ButtonState {
pub fn any_pressed(&self) -> bool {
self.a || self.b || self.c
}
pub fn all_pressed(&self) -> bool {
self.a && self.b && self.c
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ButtonLed {
value: bool,
}
impl ButtonLed {
pub const fn new() -> Self {
Self { value: false }
}
pub fn is_on(&self) -> bool {
self.value
}
pub fn on(&mut self) {
self.value = true;
}
pub fn off(&mut self) {
self.value = false;
}
pub fn set(&mut self, on: bool) {
self.value = on;
}
pub fn toggle(&mut self) {
self.value = !self.value;
}
}
pub struct Buttons<I2C> {
device: I2cDevice<I2C>,
pub led_a: ButtonLed,
pub led_b: ButtonLed,
pub led_c: ButtonLed,
current_state: ButtonState,
}
impl<I2C, E> Buttons<I2C>
where
I2C: I2c<Error = E>,
{
pub fn new(i2c: I2C) -> Result<Self, E> {
Self::new_with_address(i2c, addresses::BUTTONS)
}
pub fn discover(i2c: &mut I2C) -> Result<u8, E> {
let addresses = [addresses::BUTTONS];
for &addr in &addresses {
if i2c.write(addr, &[]).is_ok() {
return Ok(addr);
}
}
i2c.write(addresses[0], &[])
.map(|_| addresses[0])
.map_err(Error::I2c)
}
pub fn new_with_address(i2c: I2C, address: u8) -> Result<Self, E> {
let mut buttons = Self {
device: I2cDevice::new(i2c, address),
led_a: ButtonLed::new(),
led_b: ButtonLed::new(),
led_c: ButtonLed::new(),
current_state: ButtonState::default(),
};
buttons.read()?;
Ok(buttons)
}
pub fn address(&self) -> u8 {
self.device.address
}
pub fn read(&mut self) -> Result<ButtonState, E> {
let mut buf = [0u8; 4]; self.device.read(&mut buf)?;
self.current_state = ButtonState {
a: buf[1] != 0,
b: buf[2] != 0,
c: buf[3] != 0,
};
Ok(self.current_state)
}
pub fn state(&self) -> ButtonState {
self.current_state
}
pub fn button_a_pressed(&self) -> bool {
self.current_state.a
}
pub fn button_b_pressed(&self) -> bool {
self.current_state.b
}
pub fn button_c_pressed(&self) -> bool {
self.current_state.c
}
pub fn update_leds(&mut self) -> Result<(), E> {
let data = [
self.led_a.is_on() as u8,
self.led_b.is_on() as u8,
self.led_c.is_on() as u8,
];
self.device.write(&data)?;
Ok(())
}
pub fn set_leds(&mut self, a: bool, b: bool, c: bool) -> Result<(), E> {
self.led_a.set(a);
self.led_b.set(b);
self.led_c.set(c);
self.update_leds()
}
pub fn all_leds_off(&mut self) -> Result<(), E> {
self.set_leds(false, false, false)
}
pub fn all_leds_on(&mut self) -> Result<(), E> {
self.set_leds(true, true, true)
}
pub fn release(self) -> I2C {
self.device.release()
}
}