lpc8xx_hal/ctimer/
channel.rs

1//! Contains types related to CTIMER PWM channels
2
3use core::{convert::Infallible, marker::PhantomData};
4
5use embedded_hal::PwmPin;
6use embedded_hal_alpha::pwm::blocking::PwmPin as PwmPinAlpha;
7
8use crate::{
9    init_state::Enabled,
10    pac::{
11        ctimer0::{MR, MSR},
12        CTIMER0,
13    },
14    reg_proxy::RegProxy,
15};
16
17use self::state::Attached;
18
19/// A CTIMER PWM channel
20pub struct Channel<T, PeripheralState, State> {
21    mr: RegProxy<MR>,
22    msr: RegProxy<MSR>,
23    channel: PhantomData<T>,
24    peripheral_state: PhantomData<PeripheralState>,
25    _state: PhantomData<State>,
26}
27
28impl<T, PeripheralState, State> Channel<T, PeripheralState, State> {
29    pub(super) fn new() -> Self {
30        Self {
31            mr: RegProxy::new(),
32            msr: RegProxy::new(),
33            channel: PhantomData,
34            peripheral_state: PhantomData,
35            _state: PhantomData,
36        }
37    }
38}
39
40impl<T> PwmPin for Channel<T, Enabled, Attached>
41where
42    T: Trait,
43{
44    type Duty = u32;
45
46    /// The behaviour of `enable` is implementation defined and does nothing in
47    /// this implementation
48    fn enable(&mut self) {}
49
50    /// The behaviour of `disable` is implementation defined and does nothing in
51    /// this implementation
52    // Accessing pwmc would require some kind of lock, which is inconvenient
53    // and would involve a hidden `CriticalSection`
54    fn disable(&mut self) {}
55
56    /// Returns the current duty cycle
57    fn get_duty(&self) -> Self::Duty {
58        self.msr[T::ID as usize].read().match_shadow().bits()
59    }
60
61    /// Returns the maximum duty cycle value
62    fn get_max_duty(&self) -> Self::Duty {
63        self.mr[3].read().match_().bits()
64    }
65
66    /// Sets a new duty cycle
67    fn set_duty(&mut self, duty: Self::Duty) {
68        unsafe {
69            self.msr[T::ID as usize].write(|w| w.match_shadow().bits(duty))
70        };
71    }
72}
73
74impl<T> PwmPinAlpha for Channel<T, Enabled, Attached>
75where
76    T: Trait,
77{
78    type Error = Infallible;
79    type Duty = u32;
80
81    /// The behaviour of `enable` is implementation defined and does nothing in
82    /// this implementation
83    fn enable(&mut self) -> Result<(), Self::Error> {
84        Ok(())
85    }
86
87    /// The behaviour of `disable` is implementation defined and does nothing in
88    /// this implementation
89    // Accessing pwmc would require some kind of lock, which is inconvenient
90    // and would involve a hidden `CriticalSection`
91    fn disable(&mut self) -> Result<(), Self::Error> {
92        Ok(())
93    }
94
95    /// Returns the current duty cycle
96    fn get_duty(&self) -> Result<Self::Duty, Self::Error> {
97        Ok(self.msr[T::ID as usize].read().match_shadow().bits())
98    }
99
100    /// Returns the maximum duty cycle value
101    fn get_max_duty(&self) -> Result<Self::Duty, Self::Error> {
102        Ok(self.mr[3].read().match_().bits())
103    }
104
105    /// Sets a new duty cycle
106    fn set_duty(&mut self, duty: Self::Duty) -> Result<(), Self::Error> {
107        unsafe {
108            Ok(self.msr[T::ID as usize].write(|w| w.match_shadow().bits(duty)))
109        }
110    }
111}
112
113/// Implemented for all CTIMER PWM channels
114pub trait Trait: private::Sealed {
115    /// Identifies the channel
116    const ID: u8;
117
118    /// The SWM function that needs to be assigned to this channels output pin
119    type Output;
120}
121
122/// Contains types that indicate which state a channel is in
123pub mod state {
124    /// Indicates that a channel is detached
125    ///
126    /// Detached channels don't have an output function assigned and can't be
127    /// used for PWM output.
128    pub struct Detached;
129
130    /// Indicates that a channel is attached
131    pub struct Attached;
132}
133
134pub(super) mod private {
135    pub trait Sealed {}
136}
137
138reg!(MR, [MR; 4], CTIMER0, mr);
139reg!(MSR, [MSR; 4], CTIMER0, msr);