stm32_hrtim/
output.rs

1use crate::{
2    ext::{Chan, TimExt},
3    pac::HRTIM_COMMON,
4    timer::{Ch1, Ch2, ChExt, InstanceX},
5    DacResetTrigger, DacStepTrigger, NoDacTrigger,
6};
7use core::marker::PhantomData;
8
9use super::event::EventSource;
10
11impl<TIM: InstanceX, PSCL, CH: ChExt, R: DacResetTrigger, S: DacStepTrigger> HrOutput<TIM, PSCL>
12    for HrOut<TIM, PSCL, CH, R, S>
13{
14    fn enable(&mut self) {
15        let common = unsafe { &*HRTIM_COMMON::ptr() };
16        common.oenr().write(|w| match CH::CH {
17            Chan::Ch1 => w.t1oen(TIM::T_X as _).set_bit(),
18            Chan::Ch2 => w.t2oen(TIM::T_X as _).set_bit(),
19        });
20    }
21
22    fn disable(&mut self) {
23        let common = unsafe { &*HRTIM_COMMON::ptr() };
24        common.odisr().write(|w| match CH::CH {
25            Chan::Ch1 => w.t1odis(TIM::T_X as _).set_bit(),
26            Chan::Ch2 => w.t2odis(TIM::T_X as _).set_bit(),
27        });
28    }
29
30    fn enable_set_event<ES: EventSource<TIM, PSCL>>(&mut self, _set_event: &ES) {
31        let tim = unsafe { &*TIM::ptr() };
32        unsafe {
33            tim.set_r(CH::CH).modify(|r, w| w.bits(r.bits() | ES::BITS));
34        }
35    }
36    fn disable_set_event<ES: EventSource<TIM, PSCL>>(&mut self, _set_event: &ES) {
37        let tim = unsafe { &*TIM::ptr() };
38        unsafe {
39            tim.set_r(CH::CH)
40                .modify(|r, w| w.bits(r.bits() & !ES::BITS));
41        }
42    }
43
44    fn enable_rst_event<ES: EventSource<TIM, PSCL>>(&mut self, _reset_event: &ES) {
45        let tim = unsafe { &*TIM::ptr() };
46        unsafe {
47            tim.rst_r(CH::CH).modify(|r, w| w.bits(r.bits() | ES::BITS));
48        }
49    }
50    fn disable_rst_event<ES: EventSource<TIM, PSCL>>(&mut self, _reset_event: &ES) {
51        let tim = unsafe { &*TIM::ptr() };
52        unsafe {
53            tim.rst_r(CH::CH)
54                .modify(|r, w| w.bits(r.bits() & !ES::BITS));
55        }
56    }
57
58    fn get_state(&self) -> State {
59        let ods;
60        let oen;
61
62        unsafe {
63            let common = &*HRTIM_COMMON::ptr();
64            match CH::CH {
65                Chan::Ch1 => {
66                    ods = common.odsr().read().t1ods(TIM::T_X as _).bit_is_set();
67                    oen = common.oenr().read().t1oen(TIM::T_X as _).bit_is_set();
68                }
69                Chan::Ch2 => {
70                    ods = common.odsr().read().t2ods(TIM::T_X as _).bit_is_set();
71                    oen = common.oenr().read().t2oen(TIM::T_X as _).bit_is_set();
72                }
73            }
74        }
75
76        match (oen, ods) {
77            (true, _) => State::Running,
78            (false, false) => State::Idle,
79            (false, true) => State::Fault,
80        }
81    }
82}
83
84pub trait HrOutput<TIM, PSCL> {
85    /// Enable this output
86    fn enable(&mut self);
87
88    /// Disable this output
89    fn disable(&mut self);
90
91    /// Set this output to active every time the specified event occurs
92    ///
93    /// NOTE: Enabling the same event for both SET and RESET
94    /// will make that event TOGGLE the output
95    fn enable_set_event<ES: EventSource<TIM, PSCL>>(&mut self, set_event: &ES);
96
97    /// Stop listening to the specified event
98    fn disable_set_event<ES: EventSource<TIM, PSCL>>(&mut self, set_event: &ES);
99
100    /// Set this output to *not* active every time the specified event occurs
101    ///
102    /// NOTE: Enabling the same event for both SET and RESET
103    /// will make that event TOGGLE the output
104    fn enable_rst_event<ES: EventSource<TIM, PSCL>>(&mut self, reset_event: &ES);
105
106    /// Stop listening to the specified event
107    fn disable_rst_event<ES: EventSource<TIM, PSCL>>(&mut self, reset_event: &ES);
108
109    /// Get current state of the output
110    fn get_state(&self) -> State;
111}
112
113#[derive(Debug, PartialEq, Copy, Clone)]
114#[cfg_attr(feature = "defmt", derive(defmt::Format))]
115pub enum State {
116    Idle,
117    Running,
118    Fault,
119}
120
121impl State {
122    pub fn is_idle(self) -> bool {
123        matches!(self, State::Idle)
124    }
125
126    pub fn is_running(self) -> bool {
127        matches!(self, State::Running)
128    }
129
130    pub fn is_fault(self) -> bool {
131        matches!(self, State::Fault)
132    }
133}
134
135/// # Safety
136/// Caller needs to ensure that this is only implemented
137/// for types that represent pin that can act as an output
138/// for the specified timer `TIM`
139pub unsafe trait ToHrOut<TIM, DacRst = NoDacTrigger, DacStp = NoDacTrigger>
140where
141    DacRst: DacResetTrigger,
142    DacStp: DacStepTrigger,
143{
144    type Out<PSCL>;
145}
146
147unsafe impl<TIM, PA, PB, DacRst, DacStp> ToHrOut<TIM, DacRst, DacStp> for (PA, PB)
148where
149    PA: ToHrOut<TIM, DacRst, DacStp>,
150    PB: ToHrOut<TIM, DacRst, DacStp>,
151    DacRst: DacResetTrigger,
152    DacStp: DacStepTrigger,
153{
154    type Out<PSCL> = (PA::Out<PSCL>, PB::Out<PSCL>);
155}
156
157// NOTE: Only HrOut1 can actually be used as a dac trigger
158
159pub struct HrOut<
160    TIM,
161    PSCL,
162    CH,
163    DacRst: DacResetTrigger = NoDacTrigger,
164    DacStp: DacStepTrigger = NoDacTrigger,
165>(PhantomData<(TIM, PSCL, CH, DacRst, DacStp)>);
166pub type HrOut1<TIM, PSCL, DacRst = NoDacTrigger, DacStp = NoDacTrigger> =
167    HrOut<TIM, PSCL, Ch1, DacRst, DacStp>;
168pub type HrOut2<TIM, PSCL, DacRst = NoDacTrigger, DacStp = NoDacTrigger> =
169    HrOut<TIM, PSCL, Ch2, DacRst, DacStp>;
170
171unsafe impl<T> ToHrOut<T> for () {
172    type Out<PSCL> = ();
173}