embedded_c_sdk_bind_hal/pwm.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
use crate::ll_api::{ll_cmd::*, PwmCtrl};
pub use crate::ll_api::{PwmChannel, PwmPolarity};
use core::convert::Infallible;
use fugit::TimerDurationU32;
#[derive(Clone, Debug)]
pub struct Pwm<const FREQ: u32> {
ch: PwmChannel,
}
impl<const FREQ: u32> Pwm<FREQ> {
/// Creates a new PWM instance with the specified channel.
///
/// # Arguments
/// * `ch` - The PWM channel to initialize.
///
/// # Returns
/// A new `Pwm` instance configured for the given channel and frequency.
pub fn new(ch: PwmChannel) -> Self {
ll_invoke_inner!(INVOKE_ID_PWM_INIT, ch, FREQ);
Pwm { ch }
}
/// Enables the PWM output on the specified channel.
pub fn enable(&self) {
ll_invoke_inner!(INVOKE_ID_PWM_CTRL, self.ch, PwmCtrl::On);
}
/// Disables the PWM output on the specified channel.
pub fn disable(&self) {
ll_invoke_inner!(INVOKE_ID_PWM_CTRL, self.ch, PwmCtrl::Off);
}
/// Sets the polarity of the PWM output on the specified channel.
///
/// # Arguments
/// * `p` - The polarity to set (`ActiveHigh` or `ActiveLow`).
pub fn set_polarity(&self, p: PwmPolarity) {
ll_invoke_inner!(INVOKE_ID_PWM_CTRL, self.ch, p);
}
/// Retrieves the current duty cycle of the PWM output on the specified channel.
///
/// # Returns
/// The current duty cycle as a `u16`.
pub fn get_duty(&self) -> u16 {
let mut result = ll_invoke_inner!(INVOKE_ID_PWM_CTRL, self.ch, PwmCtrl::GetDuty);
if result < 0 {
result = 0;
}
result as u16
}
/// Retrieves the current duty cycle of the PWM output on the specified channel and converts it to a duration.
///
/// # Returns
/// The current duty cycle as a `TimerDurationU32`.
pub fn get_duty_time(&self) -> TimerDurationU32<FREQ> {
TimerDurationU32::from_ticks(self.get_duty() as u32)
}
/// Sets the duty cycle of the PWM output on the specified channel.
///
/// # Arguments
/// * `duty` - The duty cycle to set.
pub fn set_duty(&self, duty: u16) {
ll_invoke_inner!(INVOKE_ID_PWM_CTRL, self.ch, PwmCtrl::SetDuty, duty);
}
/// Sets the duty cycle of the PWM output on the specified channel from a duration.
///
/// # Arguments
/// * `duty` - The duty cycle duration.
pub fn set_duty_time(&self, duty: TimerDurationU32<FREQ>) {
self.set_duty(duty.ticks() as u16);
}
/// Retrieves the maximum duty cycle value of the PWM output.
///
/// # Returns
/// The maximum duty cycle as a `u16`. If `0` is returned, it means the max duty cycle is `2^16`.
pub fn get_max_duty(&self) -> u16 {
let mut result = ll_invoke_inner!(INVOKE_ID_PWM_CTRL, self.ch, PwmCtrl::GetMaxDuty);
if result < 0 {
result = 0;
}
result as u16
}
/// Retrieves the current period of the PWM output as a duration.
///
/// # Returns
/// The current period as a `TimerDurationU32`.
pub fn get_period(&self) -> TimerDurationU32<FREQ> {
let mut result = ll_invoke_inner!(INVOKE_ID_PWM_CTRL, self.ch, PwmCtrl::GetPeriod);
if result < 0 {
result = 0;
}
TimerDurationU32::from_ticks(result as u32)
}
/// Sets the PWM frequency for the PWM output from a duration.
///
/// # Arguments
/// * `period` - The desired period as a `TimerDurationU32`.
pub fn set_period(&self, period: TimerDurationU32<FREQ>) {
if !period.is_zero() {
ll_invoke_inner!(
INVOKE_ID_PWM_CTRL,
self.ch,
PwmCtrl::SetPeriod,
period.ticks()
);
}
}
}
impl<const FREQ: u32> Drop for Pwm<FREQ> {
fn drop(&mut self) {
ll_invoke_inner!(INVOKE_ID_PWM_DEINIT, self.ch);
}
}
impl<const FREQ: u32> embedded_hal::pwm::ErrorType for Pwm<FREQ> {
type Error = Infallible;
}
impl<const FREQ: u32> embedded_hal::pwm::SetDutyCycle for Pwm<FREQ> {
fn max_duty_cycle(&self) -> u16 {
self.get_max_duty()
}
fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
self.set_duty(duty);
Ok(())
}
}