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)
    }
}