embedded_c_sdk_bind_hal/
pwm.rs

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