stm32_hrtim/
external_event.rs

1use crate::pac::HRTIM_COMMON;
2use crate::Polarity;
3
4use super::control::HrTimCalibrated;
5
6#[non_exhaustive]
7#[derive(Copy, Clone, PartialEq)]
8pub struct ExternalEventSource<const N: u8, const IS_FAST: bool>;
9
10pub struct EevInputs {
11    pub eev_input1: EevInput<1>,
12    pub eev_input2: EevInput<2>,
13    pub eev_input3: EevInput<3>,
14    pub eev_input4: EevInput<4>,
15    pub eev_input5: EevInput<5>,
16    pub eev_input6: EevInput<6>,
17    pub eev_input7: EevInput<7>,
18    pub eev_input8: EevInput<8>,
19    pub eev_input9: EevInput<9>,
20    pub eev_input10: EevInput<10>,
21}
22
23impl EevInputs {
24    pub(crate) unsafe fn new() -> Self {
25        EevInputs {
26            eev_input1: EevInput,
27            eev_input2: EevInput,
28            eev_input3: EevInput,
29            eev_input4: EevInput,
30            eev_input5: EevInput,
31            eev_input6: EevInput,
32            eev_input7: EevInput,
33            eev_input8: EevInput,
34            eev_input9: EevInput,
35            eev_input10: EevInput,
36        }
37    }
38}
39
40#[non_exhaustive]
41pub struct EevInput<const N: u8>;
42
43/// This is implemented for types that can be used as inputs to the eev
44/// # Safety
45/// Only implement for types that can be used as sources to eev number `EEV_N` with src bits `SRC_BITS`
46pub unsafe trait EevSrcBits<const EEV_N: u8>: Sized {
47    const SRC_BITS: u8;
48    fn cfg(self) {}
49}
50
51#[derive()]
52pub enum EdgeOrPolarity {
53    Edge(Edge),
54    Polarity(Polarity),
55}
56
57#[derive(Copy, Clone, Debug, PartialEq)]
58pub enum Edge {
59    Rising = 0b01,
60    Falling = 0b10,
61    Both = 0b11,
62}
63
64#[derive(Copy, Clone, Debug, PartialEq)]
65pub enum EevSamplingFilter {
66    /// No filtering, fault acts asynchronously
67    ///
68    /// Note that this bypasses any f_eevs (FaultSamplingClkDiv)
69    None = 0b0000,
70
71    /// Sample directly at rate f_hrtim, with a count of 2
72    ///
73    /// Note that this bypasses: any f_eevs (FaultSamplingClkDiv)
74    HrtimN2 = 0b0001,
75
76    /// Sample directly at rate f_hrtim, with a count of 4
77    ///
78    /// Note that this bypasses any f_eevs (FaultSamplingClkDiv)
79    HrtimN4 = 0b0010,
80
81    /// Sample directly at rate f_hrtim, with a count of 8
82    ///
83    /// Note that this bypasses any f_eevs (FaultSamplingClkDiv)
84    HrtimN8 = 0b0011,
85
86    /// Sample at rate f_eevs / 2, with a count of 6
87    EevsDiv2N6 = 0b0100,
88
89    /// Sample at rate f_eevs / 2, with a count of 8
90    EevsDiv2N8 = 0b0101,
91
92    /// Sample at rate f_eevs / 4, with a count of 6
93    EevsDiv4N6 = 0b0110,
94
95    /// Sample at rate f_eevs / 4, with a count of 8
96    EevsDiv4N8 = 0b0111,
97
98    /// Sample at rate f_eevs / 8, with a count of 6
99    EevsDiv8N6 = 0b1000,
100
101    /// Sample at rate f_eevs / 8, with a count of 8
102    EevsDiv8N8 = 0b1001,
103
104    /// Sample at rate f_eevs / 16, with a count of 5
105    EevsDiv16N5 = 0b1010,
106
107    /// Sample at rate f_eevs / 16, with a count of 6
108    EevsDiv16N6 = 0b1011,
109
110    /// Sample at rate f_eevs / 16, with a count of 8
111    EevsDiv16N8 = 0b1100,
112
113    /// Sample at rate f_eevs / 32, with a count of 5
114    EevsDiv32N5 = 0b1101,
115
116    /// Sample at rate f_eevs / 32, with a count of 6
117    EevsDiv32N6 = 0b1110,
118
119    /// Sample at rate f_eevs / 32, with a count of 8
120    EevsDiv32N8 = 0b1111,
121}
122
123pub trait ExternalEventBuilder1To5 {}
124pub trait ExternalEventBuilder6To10 {}
125pub struct SourceBuilder<const N: u8, const IS_FAST: bool> {
126    /// EExSRC
127    src_bits: u8,
128
129    /// EExSNS
130    edge_or_polarity_bits: u8,
131
132    /// EExPOL
133    polarity_bit: bool,
134
135    /// EExF
136    filter_bits: u8,
137}
138
139#[cfg(feature = "stm32g4")]
140impl<const N: u8, const IS_FAST: bool> SourceBuilder<N, IS_FAST> {
141    /// # Safety
142    /// Caller needs to ensure that src_bits is a valid bit pattern
143    /// for eeXsrc bits in eecr1/2 registers for the intended input
144    pub unsafe fn new(src_bits: u8) -> Self {
145        Self {
146            src_bits,
147            edge_or_polarity_bits: 0, // Level sensitive
148            polarity_bit: false,      // Active high
149            filter_bits: 0,           // No filter
150        }
151    }
152}
153
154impl<const N: u8> SourceBuilder<N, false> {
155    pub fn edge_or_polarity(mut self, edge_or_polarity: EdgeOrPolarity) -> Self {
156        (self.edge_or_polarity_bits, self.polarity_bit) = match edge_or_polarity {
157            EdgeOrPolarity::Polarity(Polarity::ActiveHigh) => (0b00, false),
158            EdgeOrPolarity::Polarity(Polarity::ActiveLow) => (0b00, true),
159            EdgeOrPolarity::Edge(Edge::Rising) => (0b01, false),
160            EdgeOrPolarity::Edge(Edge::Falling) => (0b10, false),
161            EdgeOrPolarity::Edge(Edge::Both) => (0b11, false),
162        };
163
164        self
165    }
166}
167
168impl<const N: u8> SourceBuilder<N, true> {
169    /// Edge sensitivity not available in fast mode
170    pub fn polarity(mut self, polarity: Polarity) -> Self {
171        (self.edge_or_polarity_bits, self.polarity_bit) = match polarity {
172            Polarity::ActiveHigh => (0b00, false),
173            Polarity::ActiveLow => (0b00, true),
174        };
175
176        self
177    }
178}
179
180impl<const N: u8> SourceBuilder<N, false>
181where
182    SourceBuilder<N, false>: ExternalEventBuilder6To10,
183{
184    pub fn filter(mut self, filter: EevSamplingFilter) -> Self {
185        self.filter_bits = filter as _;
186        self
187    }
188}
189
190pub trait ToExternalEventSource<const N: u8, const IS_FAST: bool> {
191    fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource<N, IS_FAST>;
192}
193
194macro_rules! impl_eev1_5_to_es {
195    ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXfast:ident) => {
196        impl<const IS_FAST: bool> ExternalEventBuilder1To5 for SourceBuilder<$N, IS_FAST> {}
197
198        impl SourceBuilder<$N, false> {
199            pub fn fast(self) -> SourceBuilder<$N, true> {
200                let SourceBuilder {
201                    src_bits,
202                    edge_or_polarity_bits,
203                    polarity_bit,
204                    filter_bits,
205                } = self;
206
207                SourceBuilder {
208                    src_bits,
209                    edge_or_polarity_bits,
210                    polarity_bit,
211                    filter_bits,
212                }
213            }
214        }
215
216        impl<const IS_FAST: bool> ToExternalEventSource<$N, IS_FAST>
217            for SourceBuilder<$N, IS_FAST>
218        {
219            fn finalize(
220                self,
221                _calibrated: &mut HrTimCalibrated,
222            ) -> ExternalEventSource<$N, IS_FAST> {
223                let SourceBuilder {
224                    src_bits,
225                    edge_or_polarity_bits,
226                    polarity_bit,
227                    filter_bits: _,
228                } = self;
229
230                let common = unsafe { &*HRTIM_COMMON::ptr() };
231
232                // SAFETY: Thanks to, `HrTimCalibrated`, we know we have exclusive access to the register,
233                //         we also know no timers are started.
234                unsafe {
235                    common.eecr1().modify(|_r, w| {
236                        w.$eeXsrc()
237                            .bits(src_bits)
238                            .$eeXpol()
239                            .bit(polarity_bit)
240                            .$eeXsns()
241                            .bits(edge_or_polarity_bits)
242                            .$eeXfast()
243                            .bit(IS_FAST)
244                    });
245                }
246
247                ExternalEventSource
248            }
249        }
250
251        /// EEV$1 event
252        impl<const IS_FAST: bool, DST, PSCL> super::event::EventSource<DST, PSCL>
253            for ExternalEventSource<$N, IS_FAST>
254        {
255            const BITS: u32 = 1 << ($N + 20); // EEV1 is at bit 21
256        }
257    };
258}
259
260macro_rules! impl_eev6_10_to_es {
261    ($eev:ident, $N:literal, $eeXsrc:ident, $eeXpol:ident, $eeXsns:ident, $eeXf:ident) => {
262        impl ExternalEventBuilder6To10 for SourceBuilder<$N, false> {}
263
264        impl ToExternalEventSource<$N, false> for SourceBuilder<$N, false> {
265            fn finalize(self, _calibrated: &mut HrTimCalibrated) -> ExternalEventSource<$N, false> {
266                let SourceBuilder {
267                    src_bits,
268                    edge_or_polarity_bits,
269                    polarity_bit,
270                    filter_bits,
271                } = self;
272
273                let common = unsafe { &*HRTIM_COMMON::ptr() };
274
275                unsafe {
276                    common.eecr2().modify(|_r, w| {
277                        w.$eeXsrc()
278                            .bits(src_bits)
279                            .$eeXpol()
280                            .bit(polarity_bit)
281                            .$eeXsns()
282                            .bits(edge_or_polarity_bits)
283                    });
284                    common.eecr3().modify(|_r, w| w.$eeXf().bits(filter_bits));
285                }
286
287                ExternalEventSource
288            }
289        }
290
291        /// EEV$1 event
292        impl<DST, PSCL> super::event::EventSource<DST, PSCL> for ExternalEventSource<$N, false> {
293            const BITS: u32 = 1 << ($N + 20); // EEV1 is at bit 21
294        }
295    };
296}
297
298impl_eev1_5_to_es!(Eevnt1, 1, ee1src, ee1pol, ee1sns, ee1fast);
299impl_eev1_5_to_es!(Eevnt2, 2, ee2src, ee2pol, ee2sns, ee2fast);
300impl_eev1_5_to_es!(Eevnt3, 3, ee3src, ee3pol, ee3sns, ee3fast);
301impl_eev1_5_to_es!(Eevnt4, 4, ee4src, ee4pol, ee4sns, ee4fast);
302impl_eev1_5_to_es!(Eevnt5, 5, ee5src, ee5pol, ee5sns, ee5fast);
303
304impl_eev6_10_to_es!(Eevnt6, 6, ee6src, ee6pol, ee6sns, ee6f);
305impl_eev6_10_to_es!(Eevnt7, 7, ee7src, ee7pol, ee7sns, ee7f);
306impl_eev6_10_to_es!(Eevnt8, 8, ee8src, ee8pol, ee8sns, ee8f);
307impl_eev6_10_to_es!(Eevnt9, 9, ee9src, ee9pol, ee9sns, ee9f);
308impl_eev6_10_to_es!(Eevnt10, 10, ee10src, ee10pol, ee10sns, ee10f);
309
310impl<const N: u8, const IS_FAST: bool, TIM, PSCL> super::capture::CaptureEvent<TIM, PSCL>
311    for ExternalEventSource<N, IS_FAST>
312{
313    const BITS: u32 = 1 << (N + 1); // EEV1 is at bit #2 etc
314}
315
316impl<const N: u8, const IS_FAST: bool, DST, PSCL> super::event::TimerResetEventSource<DST, PSCL>
317    for ExternalEventSource<N, IS_FAST>
318{
319    const BITS: u32 = 1 << (N + 8); // EEV1 is at bit 9
320}