embedded_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 137 138 139 140 141 142 143 144 145 146 147 148 149 150
//! Pulse Width Modulation (PWM) traits.
#[cfg(feature = "defmt-03")]
use crate::defmt;
/// Error
pub trait Error: core::fmt::Debug {
/// Convert error to a generic error kind.
///
/// By using this method, errors freely defined by HAL implementations
/// can be converted to a set of generic errors upon which generic
/// code can act.
fn kind(&self) -> ErrorKind;
}
impl Error for core::convert::Infallible {
#[inline]
fn kind(&self) -> ErrorKind {
match *self {}
}
}
/// Error kind.
///
/// This represents a common set of operation errors. HAL implementations are
/// free to define more specific or additional error types. However, by providing
/// a mapping to these common errors, generic code can still react to them.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
#[non_exhaustive]
pub enum ErrorKind {
/// A different error occurred. The original error may contain more information.
Other,
}
impl Error for ErrorKind {
#[inline]
fn kind(&self) -> ErrorKind {
*self
}
}
impl core::fmt::Display for ErrorKind {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Other => write!(
f,
"A different error occurred. The original error may contain more information"
),
}
}
}
/// Error type trait.
///
/// This just defines the error type, to be used by the other traits.
pub trait ErrorType {
/// Error type
type Error: Error;
}
impl<T: ErrorType + ?Sized> ErrorType for &mut T {
type Error = T::Error;
}
/// Single PWM channel / pin.
pub trait SetDutyCycle: ErrorType {
/// Get the maximum duty cycle value.
///
/// This value corresponds to a 100% duty cycle.
fn max_duty_cycle(&self) -> u16;
/// Set the duty cycle to `duty / max_duty`.
///
/// The caller is responsible for ensuring that the duty cycle value is less than or equal to the maximum duty cycle value,
/// as reported by [`max_duty_cycle`].
///
/// [`max_duty_cycle`]: SetDutyCycle::max_duty_cycle
fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error>;
/// Set the duty cycle to 0%, or always inactive.
#[inline]
fn set_duty_cycle_fully_off(&mut self) -> Result<(), Self::Error> {
self.set_duty_cycle(0)
}
/// Set the duty cycle to 100%, or always active.
#[inline]
fn set_duty_cycle_fully_on(&mut self) -> Result<(), Self::Error> {
self.set_duty_cycle(self.max_duty_cycle())
}
/// Set the duty cycle to `num / denom`.
///
/// The caller is responsible for ensuring that `num` is less than or equal to `denom`,
/// and that `denom` is not zero.
#[inline]
fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) -> Result<(), Self::Error> {
debug_assert!(denom != 0);
debug_assert!(num <= denom);
let duty = u32::from(num) * u32::from(self.max_duty_cycle()) / u32::from(denom);
// This is safe because we know that `num <= denom`, so `duty <= self.max_duty_cycle()` (u16)
#[allow(clippy::cast_possible_truncation)]
{
self.set_duty_cycle(duty as u16)
}
}
/// Set the duty cycle to `percent / 100`
///
/// The caller is responsible for ensuring that `percent` is less than or equal to 100.
#[inline]
fn set_duty_cycle_percent(&mut self, percent: u8) -> Result<(), Self::Error> {
self.set_duty_cycle_fraction(u16::from(percent), 100)
}
}
impl<T: SetDutyCycle + ?Sized> SetDutyCycle for &mut T {
#[inline]
fn max_duty_cycle(&self) -> u16 {
T::max_duty_cycle(self)
}
#[inline]
fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
T::set_duty_cycle(self, duty)
}
#[inline]
fn set_duty_cycle_fully_off(&mut self) -> Result<(), Self::Error> {
T::set_duty_cycle_fully_off(self)
}
#[inline]
fn set_duty_cycle_fully_on(&mut self) -> Result<(), Self::Error> {
T::set_duty_cycle_fully_on(self)
}
#[inline]
fn set_duty_cycle_fraction(&mut self, num: u16, denom: u16) -> Result<(), Self::Error> {
T::set_duty_cycle_fraction(self, num, denom)
}
#[inline]
fn set_duty_cycle_percent(&mut self, percent: u8) -> Result<(), Self::Error> {
T::set_duty_cycle_percent(self, percent)
}
}