use super::*;
use crate::gpio::{self, AnyPin};
use core::marker::PhantomData;
use embassy_hal_internal::{into_ref, PeripheralRef};
pub struct Pwm<'d, T: Instance> {
_t: PhantomData<&'d T>,
_channel_1_pin: Option<PeripheralRef<'d, AnyPin>>,
_channel_1_n_pin: Option<PeripheralRef<'d, AnyPin>>,
_channel_2_pin: Option<PeripheralRef<'d, AnyPin>>,
_channel_2_n_pin: Option<PeripheralRef<'d, AnyPin>>,
_channel_3_pin: Option<PeripheralRef<'d, AnyPin>>,
_channel_3_n_pin: Option<PeripheralRef<'d, AnyPin>>,
_channel_4_pin: Option<PeripheralRef<'d, AnyPin>>,
}
impl<'d, T: Instance> Default for Pwm<'d, T> {
fn default() -> Self {
Self {
_t: PhantomData,
_channel_1_pin: None,
_channel_1_n_pin: None,
_channel_2_pin: None,
_channel_2_n_pin: None,
_channel_3_pin: None,
_channel_3_n_pin: None,
_channel_4_pin: None,
}
}
}
impl<'d, T: Instance> Pwm<'d, T> {
pub fn config(
&mut self,
channel_1_config: Option<ChannelConfig>,
channel_2_config: Option<ChannelConfig>,
channel_3_config: Option<ChannelConfig>,
channel_4_config: Option<ChannelConfig>,
) -> Self {
if let Some(config) = channel_1_config {
Self::channel_config(Channel::CH1, config)
}
if let Some(config) = channel_2_config {
Self::channel_config(Channel::CH2, config)
}
if let Some(config) = channel_3_config {
Self::channel_config(Channel::CH3, config)
}
if let Some(config) = channel_4_config {
Self::channel_config(Channel::CH4, config)
}
T::enable_auto_reload_buff(true);
Default::default()
}
fn channel_config(channel: Channel, config: ChannelConfig) {
T::set_enable_channel(channel, ChannelOutput::P, false);
T::set_enable_channel(channel, ChannelOutput::N, false);
T::set_channel_output_config(
channel,
config.mode,
config.clear,
config.fast,
config.preload,
);
T::set_channel_type(channel, ChannelType::Pwm);
if let Some(ch) = config.ch {
T::set_channel_output_effective_level(
channel,
ChannelOutput::P,
ch.polarity,
ch.state,
ch.idle_state,
);
}
if let Some(ch) = config.n_ch {
T::set_channel_output_effective_level(
channel,
ChannelOutput::N,
ch.polarity,
ch.state,
ch.idle_state,
);
}
}
pub fn new() -> Self {
Default::default()
}
}
impl<'d, T: Instance> Pwm<'d, T> {
pub fn set_channel_1_pin<OC_PIN, OC_N_PIN>(
&mut self,
oc_pin: Option<OC_PIN>,
oc_n_pin: Option<OC_N_PIN>,
) where
OC_PIN: TimerChannel1Pin<T> + 'd,
OC_N_PIN: TimerChannel1NPin<T>,
{
let oc_pin = oc_pin.map_or_else(
|| None,
|pin| {
into_ref!(pin);
pin.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::PullUp);
Some(pin.map_into())
},
);
let oc_n_pin = oc_n_pin.map_or_else(
|| None,
|pin| {
into_ref!(pin);
pin.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::PullUp);
Some(pin.map_into())
},
);
self._channel_1_pin = oc_pin;
self._channel_1_n_pin = oc_n_pin;
}
pub fn set_channel_2_pin<OC_PIN, OC_N_PIN>(
&mut self,
oc_pin: Option<OC_PIN>,
oc_n_pin: Option<OC_N_PIN>,
) where
OC_PIN: TimerChannel2Pin<T> + 'd,
OC_N_PIN: TimerChannel2NPin<T> + 'd,
{
let oc_pin = oc_pin.map_or_else(
|| None,
|pin| {
into_ref!(pin);
pin.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::PullUp);
Some(pin.map_into())
},
);
let oc_n_pin = oc_n_pin.map_or_else(
|| None,
|pin| {
into_ref!(pin);
pin.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::PullUp);
Some(pin.map_into())
},
);
self._channel_2_pin = oc_pin;
self._channel_2_n_pin = oc_n_pin;
}
pub fn set_channel_3_pin<OC_PIN, OC_N_PIN>(
&mut self,
oc_pin: Option<OC_PIN>,
oc_n_pin: Option<OC_N_PIN>,
) where
OC_PIN: TimerChannel3Pin<T> + 'd,
OC_N_PIN: TimerChannel3NPin<T> + 'd,
{
let oc_pin = oc_pin.map_or_else(
|| None,
|pin| {
into_ref!(pin);
pin.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::PullUp);
Some(pin.map_into())
},
);
let oc_n_pin = oc_n_pin.map_or_else(
|| None,
|pin| {
into_ref!(pin);
pin.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::PullUp);
Some(pin.map_into())
},
);
self._channel_3_pin = oc_pin;
self._channel_3_n_pin = oc_n_pin;
}
pub fn set_channel_4_pin<OC_PIN, OC_N_PIN>(&mut self, oc_pin: Option<OC_PIN>)
where
OC_PIN: TimerChannel4Pin<T> + 'd,
{
let oc_pin = oc_pin.map_or_else(
|| None,
|pin| {
into_ref!(pin);
pin.set_instance_af(gpio::PinSpeed::VeryHigh, gpio::PinIoType::PullUp);
Some(pin.map_into())
},
);
self._channel_4_pin = oc_pin;
}
}
impl<'d, T: Instance> Pwm<'d, T> {
pub fn enable(&mut self, channel: Channel) {
T::set_enable_channel(channel, ChannelOutput::P, true);
T::set_enable_channel(channel, ChannelOutput::N, true);
}
pub fn disable(&mut self, channel: Channel) {
T::set_enable_channel(channel, ChannelOutput::P, false);
T::set_enable_channel(channel, ChannelOutput::N, false);
}
pub fn get_duty(&self, channel: Channel) -> u16 {
T::get_channel_capture(channel)
}
pub fn get_max_duty(&self) -> u16 {
T::get_reload()
}
pub fn set_frequency(&mut self, freq: u32) {
let freq = if T::get_time_pclk() <= freq {
T::get_time_pclk()
} else {
freq
};
let pre = T::get_time_pclk() / freq;
T::set_prescaler(pre as u16 - 1);
}
fn get_period(&self) -> u16 {
T::get_reload()
}
fn set_duty(&mut self, channel: Channel, duty: u16) {
let duty = if duty > self.get_max_duty() {
self.get_max_duty()
} else {
duty
};
T::set_channel_compare(channel, duty);
}
fn set_period(&mut self, period: u16) {
T::set_auto_reload(period)
}
pub fn start(&mut self) {
T::enable_channel_output(true);
T::start();
}
pub fn stop(&mut self) {
T::enable_channel_output(false);
T::stop()
}
}
impl<'d, T: Instance> embedded_hal::Pwm for Pwm<'d, T> {
type Channel = Channel;
type Duty = u16;
type Time = u16;
fn enable(&mut self, channel: Self::Channel) {
self.enable(channel)
}
fn disable(&mut self, channel: Self::Channel) {
self.disable(channel)
}
fn get_duty(&self, channel: Self::Channel) -> Self::Duty {
self.get_duty(channel)
}
fn get_max_duty(&self) -> Self::Duty {
self.get_max_duty()
}
fn get_period(&self) -> Self::Time {
self.get_period()
}
fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) {
self.set_duty(channel, duty)
}
fn set_period<P>(&mut self, period: P)
where
P: Into<Self::Time>,
{
self.set_period(period.into())
}
}