lilkaoxide 0.1.0

Rust support library for Lilka console
use crate::cfg::BuzzerConfig;
use esp_hal::gpio::{DriveMode, interconnect::PeripheralOutput};
use esp_hal::ledc::{
    LSGlobalClkSource, Ledc, LowSpeed, channel, channel::ChannelIFace, timer, timer::TimerIFace,
};
use esp_hal::peripherals::LEDC;
use static_cell::StaticCell;

type BuzzerTimer = timer::Timer<'static, LowSpeed>;
type BuzzerChannel = channel::Channel<'static, LowSpeed>;

static BUZZER_TIMER: StaticCell<BuzzerTimer> = StaticCell::new();

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BuzzerInitError {
    Timer(timer::Error),
    Channel(channel::Error),
}

impl BuzzerInitError {
    pub const fn as_str(self) -> &'static str {
        match self {
            Self::Timer(_) => "Buzzer timer init failed",
            Self::Channel(_) => "Buzzer channel init failed",
        }
    }
}

pub struct Buzzer {
    pub channel: BuzzerChannel,
}

pub fn init_buzzer(
    config: BuzzerConfig,
    ledc_peripheral: LEDC<'static>,
    buzzer_pin: impl PeripheralOutput<'static>,
) -> Result<Buzzer, BuzzerInitError> {
    let mut ledc = Ledc::new(ledc_peripheral);
    ledc.set_global_slow_clock(LSGlobalClkSource::APBClk);

    let timer = BUZZER_TIMER.init(ledc.timer::<LowSpeed>(timer::Number::Timer0));
    timer
        .configure(timer::config::Config {
            duty: config.timer_duty,
            clock_source: timer::LSClockSource::APBClk,
            frequency: config.frequency,
        })
        .map_err(BuzzerInitError::Timer)?;

    let mut channel = ledc.channel::<LowSpeed>(channel::Number::Channel0, buzzer_pin);
    channel
        .configure(channel::config::Config {
            timer,
            duty_pct: config.duty_pct.min(100),
            drive_mode: DriveMode::PushPull,
        })
        .map_err(BuzzerInitError::Channel)?;

    Ok(Buzzer { channel })
}