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,
];
}