use esp_idf_hal::gpio::OutputPin; use esp_idf_hal::ledc; use esp_idf_hal::ledc::{config::TimerConfig, Channel, Timer}; use esp_idf_hal::prelude::*; use esp_idf_sys::EspError; use std::thread; use std::time::Duration; type LedcChannel = Channel, P>; pub struct Beep { beat: u8, ringtone: ringtone::Type, channel: LedcChannel, duty: u32, } impl Beep { pub fn new(pin: P, timer: T, channel: C) -> Result { let channel = Self::init_channel(pin, timer, channel)?; let max_duty = channel.get_max_duty(); return Ok(Beep { channel, beat: 0, duty: max_duty * 3 / 4, ringtone: ringtone::SILENCE, }); } fn init_channel(pin: P, timer: T, channel: C) -> Result, EspError> { let config = TimerConfig::default().frequency(2.kHz().into()); let timer = Timer::new(timer, &config)?; let channel: Channel, P> = Channel::new(channel, timer, pin)?; return Ok(channel); } pub fn play(&mut self, rx: &mut std::sync::mpsc::Receiver) { loop { let curr_ringtone = rx.try_recv().unwrap_or_else(|_| self.ringtone); if !curr_ringtone.eq(&mut self.ringtone) { self.beat = 0; self.ringtone = curr_ringtone; } let curr = curr_ringtone[self.beat as usize]; if curr { self.channel.set_duty(self.duty).expect("Failed to set duty"); } else { self.channel.set_duty(0).expect("Failed to set duty"); } thread::sleep(Duration::from_millis(100)); self.beat += 1; if self.beat == 16 { self.beat = 0; } } } } pub mod ringtone { pub type Type = [bool; 16]; pub const ADAPTER_DOWN: Type = [ true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, ]; pub const BATTERY_LOW: Type = [ true, true, false, false, true, true, false, false, true, true, false, false, true, true, false, false, ]; pub const SILENCE: Type = [false; 16]; pub const SHUTDOWN: Type = [ true, false, true, true, true, true, false, true, true, true, true, true, false, false, false, false, ]; }