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))]
#[repr(u8)]
pub enum PowerLevel {
Stop = 0,
Gentle = 25,
Moderate = 30,
#[default]
Medium = 35,
Intense = 40,
Powerful = 45,
Maximum = 50,
}
impl PowerLevel {
pub const fn value(&self) -> u8 {
*self as u8
}
}
impl From<PowerLevel> for u8 {
fn from(level: PowerLevel) -> Self {
level.value()
}
}
pub struct Vibro<I2C> {
device: I2cDevice<I2C>,
frequency: u32,
}
impl<I2C, E> Vibro<I2C>
where
I2C: I2c<Error = E>,
{
pub const DEFAULT_FREQUENCY: u32 = 1000;
pub fn new(i2c: I2C) -> Result<Self, E> {
Self::new_with_address(i2c, addresses::VIBRO)
}
pub fn discover(i2c: &mut I2C) -> Result<u8, E> {
let addresses = [addresses::VIBRO];
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 vibro = Self {
device: I2cDevice::new(i2c, address),
frequency: Self::DEFAULT_FREQUENCY,
};
vibro.off()?;
Ok(vibro)
}
pub fn address(&self) -> u8 {
self.device.address
}
pub fn frequency(&self) -> u32 {
self.frequency
}
pub fn set_frequency(&mut self, frequency: u32) {
self.frequency = frequency;
}
pub fn on(&mut self, duration_ms: u16, power: PowerLevel) -> Result<(), E> {
self.on_with_power(duration_ms, power.value())
}
pub fn on_with_power(&mut self, duration_ms: u16, power: u8) -> Result<(), E> {
let freq_bytes = self.frequency.to_le_bytes();
let duration_bytes = (duration_ms as u32).to_le_bytes();
let power_bytes = (power as u32).to_le_bytes();
let data = [
freq_bytes[0],
freq_bytes[1],
freq_bytes[2],
freq_bytes[3],
duration_bytes[0],
duration_bytes[1],
duration_bytes[2],
duration_bytes[3],
power_bytes[0],
power_bytes[1],
power_bytes[2],
power_bytes[3],
];
self.device.write(&data)?;
Ok(())
}
pub fn on_continuous(&mut self, power: PowerLevel) -> Result<(), E> {
self.on(0xFFFF, power)
}
pub fn off(&mut self) -> Result<(), E> {
let data = [0u8; 8];
self.device.write(&data)?;
Ok(())
}
pub fn stop(&mut self) -> Result<(), E> {
self.off()
}
pub fn pulse(&mut self, on_ms: u16, power: PowerLevel) -> Result<(), E> {
self.on(on_ms, power)
}
pub fn release(self) -> I2C {
self.device.release()
}
}