use crate::{addresses, Error, I2cDevice, Result};
use embedded_hal::i2c::I2c;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(u16)]
#[allow(missing_docs)]
pub enum Note {
FS3 = 185,
G3 = 196,
GS3 = 208,
A3 = 220,
AS3 = 233,
B3 = 247,
C4 = 262,
CS4 = 277,
D4 = 294,
DS4 = 311,
E4 = 330,
F4 = 349,
FS4 = 370,
G4 = 392,
GS4 = 415,
A4 = 440,
AS4 = 466,
B4 = 494,
C5 = 523,
CS5 = 554,
D5 = 587,
DS5 = 622,
E5 = 659,
F5 = 698,
FS5 = 740,
G5 = 784,
GS5 = 831,
A5 = 880,
AS5 = 932,
B5 = 988,
C6 = 1047,
CS6 = 1109,
D6 = 1175,
DS6 = 1245,
E6 = 1319,
F6 = 1397,
FS6 = 1480,
G6 = 1568,
GS6 = 1661,
A6 = 1760,
AS6 = 1865,
B6 = 1976,
C7 = 2093,
CS7 = 2217,
D7 = 2349,
DS7 = 2489,
E7 = 2637,
F7 = 2794,
FS7 = 2960,
G7 = 3136,
GS7 = 3322,
A7 = 3520,
AS7 = 3729,
B7 = 3951,
C8 = 4186,
CS8 = 4435,
D8 = 4699,
DS8 = 4978,
Rest = 0,
}
impl Note {
pub const fn frequency(&self) -> u16 {
*self as u16
}
}
impl From<Note> for u16 {
fn from(note: Note) -> Self {
note.frequency()
}
}
pub struct Buzzer<I2C> {
device: I2cDevice<I2C>,
}
impl<I2C, E> Buzzer<I2C>
where
I2C: I2c<Error = E>,
{
pub const MIN_FREQUENCY: u16 = 180;
pub fn new(i2c: I2C) -> Result<Self, E> {
Self::new_with_address(i2c, addresses::BUZZER)
}
pub fn discover(i2c: &mut I2C) -> Result<u8, E> {
let addresses = [addresses::BUZZER];
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 buzzer = Self {
device: I2cDevice::new(i2c, address),
};
buzzer.no_tone()?;
Ok(buzzer)
}
pub fn address(&self) -> u8 {
self.device.address
}
pub fn tone(&mut self, frequency: u16, duration_ms: u16) -> Result<(), E> {
let freq_bytes = (frequency as u32).to_le_bytes();
let duration_bytes = (duration_ms 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],
];
self.device.write(&data)?;
Ok(())
}
pub fn tone_continuous(&mut self, frequency: u16) -> Result<(), E> {
self.tone(frequency, 0xFFFF)
}
pub fn play_note(&mut self, note: Note, duration_ms: u16) -> Result<(), E> {
self.tone(note.frequency(), duration_ms)
}
pub fn no_tone(&mut self) -> Result<(), E> {
let data = [0u8; 8];
self.device.write(&data)?;
Ok(())
}
pub fn stop(&mut self) -> Result<(), E> {
self.no_tone()
}
pub fn release(self) -> I2C {
self.device.release()
}
}