stm32_hal2/
timer.rs

1//! Provides support for basic timer functionality. Includes initialization, interrupts,
2//! and PWM features. Also supports capture compare, output compare, burst DMA, and getting the current uptime using
3//! an overflowing wrapper. (In seconds, milliseconds, or microseconds)
4//!
5//! Low-power timers (LPTIM) and high-presolution timers (HRTIM) are not yet supported.
6
7// todo: WB and WL should support pwm features
8
9#[cfg(feature = "monotonic")]
10use core;
11use core::{
12    ops::Deref,
13    sync::atomic::{AtomicU32, Ordering},
14    time::Duration,
15};
16
17use cfg_if::cfg_if;
18use paste::paste;
19#[cfg(feature = "monotonic")]
20use rtic_monotonic::Monotonic;
21
22cfg_if! {
23    if #[cfg(feature = "embedded_hal")] {
24        // use embedded_hal::{
25        //     blocking::delay::{DelayMs, DelayUs},
26        //     timer::CountDown,
27        // };
28        // use embedded_time::{rate::Hertz, duration};
29        // use void::Void;
30    }
31}
32
33use num_traits::float::FloatCore; // To round floats.
34
35#[cfg(any(feature = "f3", feature = "l4"))]
36use crate::dma::DmaInput;
37#[cfg(not(any(feature = "f4", feature = "l552")))]
38use crate::dma::{self, ChannelCfg, DmaChannel};
39#[cfg(feature = "g0")]
40use crate::pac::DMA as DMA1;
41#[cfg(not(feature = "g0"))]
42use crate::pac::DMA1;
43// todo: LPTIM (low-power timers) and HRTIM (high-resolution timers). And Advanced control functionality
44use crate::{
45    clocks::Clocks,
46    instant::Instant,
47    pac::{self, RCC},
48    util::{RccPeriph, rcc_en_reset},
49};
50
51// This `TICK_OVERFLOW_COUNT` must be incremented in firmware in the timer's update interrupt.
52pub static TICK_OVERFLOW_COUNT: AtomicU32 = AtomicU32::new(0);
53
54// todo: Low power timer enabling etc. eg on L4, RCC_APB1ENR1.LPTIM1EN
55
56#[derive(Clone, Copy, Debug, defmt::Format)]
57/// Used for when attempting to set a timer period that is out of range.
58pub struct ValueError {}
59
60#[derive(Clone, Copy)]
61#[repr(u8)]
62/// This bit-field selects the trigger input to be used to synchronize the counter.
63/// Sets SMCR register, TS field.
64pub enum InputTrigger {
65    ///Internal Trigger 0 (ITR0)
66    Internal0 = 0b00000,
67    Internal1 = 0b00001,
68    Internal2 = 0b00010,
69    Internal3 = 0b00011,
70    /// TI1 Edge Detector (TI1F_ED)
71    Ti1Edge = 0b00100,
72    FilteredTimerInput1 = 0b00101,
73    FilteredTimerInput2 = 0b00110,
74    ExternalTriggerInput = 0b00111,
75    Internal4 = 0b01000,
76    Internal5 = 0b01001,
77    Internal6 = 0b01010,
78    Internal7 = 0b01011,
79    Internal8 = 0b01100,
80    Internal9 = 0b01101,
81    Internal10 = 0b01110,
82    Internal11 = 0b01111,
83    Internal12 = 0b10000,
84    Internal13 = 0b10001,
85}
86
87#[derive(Clone, Copy)]
88#[repr(u8)]
89/// When external signals are selected the active edge of the trigger signal (TRGI) is linked to
90/// the polarity selected on the external input (see Input Control register and Control Register
91/// description. Sets SMCR register, SMS field.
92pub enum InputSlaveMode {
93    /// Slave mode disabled - if CEN = ‘1 then the prescaler is clocked directly by the internal
94    /// clock
95    Disabled = 0b0000,
96    /// Encoder mode 1 - Counter counts up/down on TI1FP1 edge depending on TI2FP2
97    /// level
98    Encoder1 = 0b0001,
99    /// Encoder mode 2 - Counter counts up/down on TI2FP2 edge depending on TI1FP1
100    /// level.
101    Encoder2 = 0b0010,
102    /// Encoder mode 3 - Counter counts up/down on both TI1FP1 and TI2FP2 edges
103    /// depending on the level of the other input.
104    Encoder3 = 0b0011,
105    /// Reset mode - Rising edge of the selected trigger input (TRGI) reinitializes the counter
106    /// and generates an update of the registers.
107    Reset = 0b0100,
108    /// Gated Mode - The counter clock is enabled when the trigger input (TRGI) is high. The
109    /// counter stops (but is not reset) as soon as the trigger becomes low. Both start and stop of
110    /// the counter are controlled.
111    Gated = 0b0101,
112    /// Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not
113    /// reset). Only the start of the counter is controlled.
114    Trigger = 0b0110,
115    /// External Clock Mode 1 - Rising edges of the selected trigger (TRGI) clock the counter.
116    ExternalClock1 = 0b0111,
117    /// Combined reset + trigger mode - Rising edge of the selected trigger input (TRGI)
118    /// reinitializes the counter, generates an update of the registers and starts the counter.
119    CombinedResetTrigger = 0b1000,
120}
121
122#[derive(Clone, Copy)]
123#[repr(u8)]
124/// These bits allow selected information to be sent in master mode to slave timers for
125/// synchronization (TRGO). Sets CR2 register, MMS field.
126pub enum MasterModeSelection {
127    /// Tthe UG bit from the TIMx_EGR register is used as trigger output (TRGO). If the
128    /// reset is generated by the trigger input (slave mode controller configured in reset mode) then
129    /// the signal on TRGO is delayed compared to the actual reset.
130    Reset = 0b000,
131    /// the Counter Enable signal CNT_EN is used as trigger output (TRGO). It is
132    /// useful to start several timers at the same time or to control a window in which a slave timer is
133    /// enable. The Counter Enable signal is generated by a logic AND between CEN control bit
134    /// and the trigger input when configured in gated mode. When the Counter Enable signal is
135    /// controlled by the trigger input, there is a delay on TRGO, except if the master/slave mode is
136    /// selected (see the MSM bit description in TIMx_SMCR register).
137    Enable = 0b001,
138    /// The update event is selected as trigger output (TRGO). For instance a master
139    /// timer can then be used as a prescaler for a slave timer.
140    Update = 0b010,
141    /// Compare Pulse - The trigger output send a positive pulse when the CC1IF flag is to be
142    /// set (even if it was already high), as soon as a capture or a compare match occurred.
143    /// (TRGO).
144    ComparePulse = 0b011,
145    /// OC1REF signal is used as trigger output (TRGO)
146    Compare1 = 0b100,
147    /// OC2REF signal is used as trigger output (TRGO)
148    Compare2 = 0b101,
149    /// OC3REF signal is used as trigger output (TRGO)
150    Compare3 = 0b110,
151    /// OC4REF signal is used as trigger output (TRGO)
152    Compare4 = 0b111,
153}
154
155/// Timer interrupt
156pub enum TimerInterrupt {
157    /// Update interrupt can be used for a timeout. DIER UIE to set, ... to clear
158    Update,
159    /// Trigger. DIER TIE to set, ... to clear
160    Trigger,
161    /// Capture/Compare. CC1IE to set, ... to clear
162    CaptureCompare1,
163    /// Capture/Compare. CC2IE to set, ... to clear
164    CaptureCompare2,
165    /// Capture/Compare. CC3IE to set, ... to clear
166    CaptureCompare3,
167    /// Capture/Compare. CC4IE to set, ... to clear
168    CaptureCompare4,
169    /// Update DMA. DIER UDE to set, ... to clear
170    UpdateDma,
171    /// Drigger. TDE to set, ... to clear
172    TriggerDma,
173    /// Capture/Compare. CC1DE to set, ... to clear
174    CaptureCompare1Dma,
175    /// Capture/Compare. CC2DE to set, ... to clear
176    CaptureCompare2Dma,
177    /// Capture/Compare. CC3DE to set, ... to clear
178    CaptureCompare3Dma,
179    /// Capture/Compare. CC4DE to set, ... to clear
180    CaptureCompare4Dma,
181}
182
183/// Output alignment. Sets `TIMx_CR1` register, `CMS` field.
184#[derive(Clone, Copy)]
185pub enum Alignment {
186    /// Edge-aligned mode. The counter counts up or down depending on the direction bit
187    /// (DIR).
188    Edge = 0b00,
189    /// Center-aligned mode 1. The counter counts up and down alternatively. Output compare
190    /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
191    /// only when the counter is counting down.
192    Center1 = 0b01,
193    /// Center-aligned mode 2. The counter counts up and down alternatively. Output compare
194    /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
195    /// only when the counter is counting up.
196    Center2 = 0b10,
197    /// Center-aligned mode 3. The counter counts up and down alternatively. Output compare
198    /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
199    /// both when the counter is counting up or down.
200    Center3 = 0b11,
201}
202
203/// Timer channel
204#[derive(Clone, Copy)]
205pub enum TimChannel {
206    C1,
207    C2,
208    C3,
209    #[cfg(not(feature = "wl"))]
210    C4,
211}
212
213/// Timer count direction. Defaults to `Up`.
214#[repr(u8)]
215#[derive(Clone, Copy)]
216pub enum CountDir {
217    Up = 0,
218    Down = 1,
219}
220
221/// Capture/Compare selection.
222/// This field defines the direction of the channel (input/output) as well as the used input.
223/// It affects the TIMx_CCMR1 register, CCxS fields. Note that the signifiders of the input sources
224/// varies depending on the channel. For example, the one labeled `InputTi1` here is always the associated
225/// channel, while `InputTi2` is 2 for ch1, 1 for ch2, 4 for ch3, and 3 for ch4.
226#[repr(u8)]
227#[derive(Clone, Copy)]
228pub enum CaptureCompare {
229    Output = 0b00,
230    InputTi1 = 0b01,
231    InputTi2 = 0b10,
232    InputTrc = 0b11,
233}
234
235/// Capture/Compare output polarity. Defaults to `ActiveHigh` in hardware. Sets TIMx_CCER register,
236/// CCxP and CCXNP fields.
237#[derive(Clone, Copy)]
238pub enum Polarity {
239    ActiveHigh,
240    ActiveLow,
241}
242
243impl Polarity {
244    /// For use with `set_bit()`.
245    fn bit(&self) -> bool {
246        match self {
247            Self::ActiveHigh => false,
248            Self::ActiveLow => true,
249        }
250    }
251}
252
253#[derive(Clone, Copy)]
254#[repr(u8)]
255/// See F303 ref man, section 21.4.7. H745 RM, section 41.4.8. Sets TIMx_CCMR1 register, OC1M field.
256/// These bits define the behavior of the output reference signal OC1REF from which OC1 and
257/// OC1N are derived. OC1REF is active high whereas OC1 and OC1N active level depends
258/// on CC1P and CC1NP bits.
259pub enum OutputCompare {
260    /// Frozen - The comparison between the output compare register TIMx_CCR1 and the
261    /// counter TIMx_CNT has no effect on the outputs.(this mode is used to generate a timing
262    /// base).
263    Frozen = 0b0000,
264    /// Set channel 1 to active level on match. OC1REF signal is forced high when the
265    /// counter TIMx_CNT matches the capture/compare register 1 (TIMx_CCR1).
266    Active = 0b0001,
267    /// Set channel 1 to inactive level on match. OC1REF signal is forced low when the
268    /// counter TIMx_CNT matches the capture/compare register 1 (TIMx_CCR1).
269    /// 0011: Toggle - OC1REF toggles when TIMx_CNT=TIMx_CCR1.
270    Inactive = 0b0010,
271    /// tim_oc1ref toggles when TIMx_CNT=TIMx_CCR1.
272    Toggle = 0b0011,
273    /// Force inactive level - OC1REF is forced low.
274    ForceInactive = 0b0100,
275    /// Force active level - OC1REF is forced high.
276    ForceActive = 0b0101,
277    /// PWM mode 1 - In upcounting, channel 1 is active as long as TIMx_CNT<TIMx_CCR1
278    /// else inactive. In downcounting, channel 1 is inactive (OC1REF=‘0) as long as
279    /// TIMx_CNT>TIMx_CCR1 else active (OC1REF=1).
280    Pwm1 = 0b0110,
281    /// PWM mode 2 - In upcounting, channel 1 is inactive as long as
282    /// TIMx_CNT<TIMx_CCR1 else active. In downcounting, channel 1 is active as long as
283    /// TIMx_CNT>TIMx_CCR1 else inactive.
284    Pwm2 = 0b0111,
285    /// Retriggerable OPM mode 1 - In up-counting mode, the channel is active until a trigger
286    /// event is detected (on TRGI signal). Then, a comparison is performed as in PWM mode 1
287    /// and the channels becomes inactive again at the next update. In down-counting mode, the
288    /// channel is inactive until a trigger event is detected (on TRGI signal). Then, a comparison is
289    /// performed as in PWM mode 1 and the channels becomes inactive again at the next update.
290    RetriggerableOpmMode1 = 0b1000,
291    /// Retriggerable OPM mode 2 - In up-counting mode, the channel is inactive until a
292    /// trigger event is detected (on TRGI signal). Then, a comparison is performed as in PWM
293    /// mode 2 and the channels becomes inactive again at the next update. In down-counting
294    /// mode, the channel is active until a trigger event is detected (on TRGI signal). Then, a
295    /// comparison is performed as in PWM mode 1 and the channels becomes active again at the
296    /// next update.
297    RetriggerableOpmMode2 = 0b1001,
298    /// Combined PWM mode 1 - OC1REF has the same behavior as in PWM mode 1.
299    /// OC1REFC is the logical OR between OC1REF and OC2REF.
300    CombinedPwm1 = 0b1100,
301    /// Combined PWM mode 2 - OC1REF has the same behavior as in PWM mode 2.
302    /// OC1REFC is the logical AND between OC1REF and OC2REF.
303    CombinedPwm2 = 0b1101,
304    /// Asymmetric PWM mode 1 - OC1REF has the same behavior as in PWM mode 1.
305    /// OC1REFC outputs OC1REF when the counter is counting up, OC2REF when it is counting
306    /// down.
307    AsymmetricPwm1 = 0b1110,
308    /// Asymmetric PWM mode 2 - OC1REF has the same behavior as in PWM mode 2.
309    /// /// OC1REFC outputs OC1REF when the counter is counting up, OC2REF when it is counting
310    /// down
311    AsymmetricPwm2 = 0b1111,
312}
313
314/// Update Request source. This bit is set and cleared by software to select the UEV event sources.
315/// Sets `TIMx_CR1` register, `URS` field.
316#[derive(Clone, Copy)]
317#[repr(u8)]
318pub enum UpdateReqSrc {
319    /// Any of the following events generate an update interrupt or DMA request.
320    /// These events can be:
321    /// – Counter overflow/underflow
322    /// – Setting the UG bit
323    /// – Update generation through the slave mode controller
324    Any = 0,
325    /// Only counter overflow/underflow generates an update interrupt or DMA request.
326    OverUnderFlow = 1,
327}
328
329/// Capture/Compaer DMA selection.
330/// Sets `TIMx_CR2` register, `CCDS` field.
331#[derive(Clone, Copy)]
332#[repr(u8)]
333pub enum CaptureCompareDma {
334    /// CCx DMA request sent when CCx event occur
335    Ccx = 0,
336    /// CCx DMA request sent when update event occurs
337    Update = 1,
338}
339
340/// Initial configuration data for Timer peripherals.
341#[derive(Clone)]
342pub struct TimerConfig {
343    /// If `one_pulse_mode` is true, the counter stops counting at the next update event
344    /// (clearing the bit CEN). If false, Counter is not stopped at update event. Defaults to false.
345    /// Sets `TIMx_CR` register, `OPM` field.
346    pub one_pulse_mode: bool,
347    /// Update request source. Ie, counter overflow/underflow only, or any. defaults to any.
348    pub update_request_source: UpdateReqSrc,
349    /// Set `true` to buffer the preload. Useful when changing period and duty while the timer is running.
350    /// Default to false.
351    pub auto_reload_preload: bool,
352    /// Select center or edge alignment. Defaults to edge.
353    pub alignment: Alignment,
354    /// Sets when CCx DMA requests occur. Defaults to on CCx event.
355    pub capture_compare_dma: CaptureCompareDma,
356    /// Timer counting direction. Defaults to up.
357    pub direction: CountDir,
358}
359
360impl Default for TimerConfig {
361    fn default() -> Self {
362        Self {
363            one_pulse_mode: false,
364            update_request_source: UpdateReqSrc::Any,
365            auto_reload_preload: false,
366            alignment: Alignment::Edge,
367            capture_compare_dma: CaptureCompareDma::Ccx,
368            direction: CountDir::Up,
369        }
370    }
371}
372
373/// Represents a General Purpose or Advanced Control timer.
374pub struct Timer<TIM> {
375    /// Register block for the specific timer.
376    pub regs: TIM,
377    /// Our config stucture, for configuration that is written to the timer hardware on initialization
378    /// via the constructor.
379    pub cfg: TimerConfig,
380    /// Associated timer clock speed in Hz.
381    clock_speed: u32,
382    // #[cfg(feature = "monotonic")]
383    // /// Used to indicate the timer has expired, and running time counts (eg the `time_elapsed()` method) properly
384    // /// increment.
385    // pub wrap_count: u32,
386    // #[cfg(feature = "monotonic")]
387    /// Updated in the constructor and `set_freq` fns. Used for mapping timer ticks to time (eg in
388    /// seconds, us etc)
389    ns_per_tick: u64,
390    period: f32, // In seconds. Used for overflow tracking. Updated when `ns_per_tick` is.
391}
392
393macro_rules! make_timer {
394    ($TIMX:ident, $tim:ident, $apb:expr, $res:ident) => {
395        impl Timer<pac::$TIMX> {
396            paste! {
397                /// Initialize a DFSDM peripheral, including  enabling and resetting
398                /// its RCC peripheral clock.
399                pub fn [<new_ $tim>](regs: pac::$TIMX, freq: f32, cfg: TimerConfig, clocks: &Clocks) -> Self {
400                    let rcc = unsafe { &(*RCC::ptr()) };
401
402                    // `freq` is in Hz.
403                    rcc_en_reset!([<apb $apb>], $tim, rcc);
404
405                    let clock_speed = match $apb {
406                        1 => clocks.apb1_timer(),
407                        _ => clocks.apb2_timer(),
408                    };
409
410
411                    regs.cr1.modify(|_, w| {
412                        #[cfg(not(feature = "f373"))]
413                        w.opm().bit(cfg.one_pulse_mode);
414                        w.urs().bit(cfg.update_request_source as u8 != 0);
415                        w.arpe().bit(cfg.auto_reload_preload)
416                    });
417
418                    #[cfg(not(feature = "f373"))]
419                    regs.cr2.modify(|_, w| {
420                        w.ccds().bit(cfg.capture_compare_dma as u8 != 0)
421                    });
422
423                    let mut result = Timer {
424                        clock_speed,
425                        cfg,
426                        regs,
427                        // #[cfg(feature = "monotonic")]
428                        // wrap_count: 0,
429                        // #[cfg(feature = "monotonic")]
430                        ns_per_tick: 0, // set below
431                        period: 0., // set below.
432                    };
433
434                    result.set_freq(freq).ok();
435                    result.set_dir();
436
437                    // Trigger an update event to load the prescaler value to the clock
438                    // NOTE(write): uses all bits in this register. This also clears the interrupt flag,
439                    // which the EGER update will generate.
440                    result.reinitialize();
441
442                    result
443                }
444            }
445
446            /// Enable a specific type of Timer interrupt.
447            pub fn enable_interrupt(&mut self, interrupt: TimerInterrupt) {
448                match interrupt {
449                    TimerInterrupt::Update => self.regs.dier.modify(|_, w| w.uie().set_bit()),
450                    // todo: Only DIER is in PAC, or some CCs. PAC BUG? Only avail on some timers/MCUs?
451                    // TimerInterrupt::Trigger => self.regs.dier.modify(|_, w| w.tie().set_bit()),
452                    // TimerInterrupt::CaptureCompare1 => self.regs.dier.modify(|_, w| w.cc1ie().set_bit()),
453                    // TimerInterrupt::CaptureCompare2 => self.regs.dier.modify(|_, w| w.cc2ie().set_bit()),
454                    // TimerInterrupt::CaptureCompare3 => self.regs.dier.modify(|_, w| w.cc3ie().set_bit()),
455                    // TimerInterrupt::CaptureCompare4 => self.regs.dier.modify(|_, w| w.cc4ie().set_bit()),
456                    #[cfg(not(feature = "f3"))] // todo: Not working on some variants
457                    TimerInterrupt::UpdateDma => self.regs.dier.modify(|_, w| w.ude().set_bit()),
458                    // TimerInterrupt::TriggerDma => self.regs.dier.modify(|_, w| w.tde().set_bit()),
459                    // TimerInterrupt::CaptureCompare1Dma => self.regs.dier.modify(|_, w| w.cc1de().set_bit()),
460                    // TimerInterrupt::CaptureCompare2Dma => self.regs.dier.modify(|_, w| w.ccd2de().set_bit()),
461                    // TimerInterrupt::CaptureCompare3Dma => self.regs.dier.modify(|_, w| w.cc3de().set_bit()),
462                    // TimerInterrupt::CaptureCompare4Dma => self.regs.dier.modify(|_, w| w.cc4de().set_bit()),
463                    _ => unimplemented!("TODO TEMP PROBLEMS"),
464                }
465            }
466
467            /// Disable a specific type of Timer interrupt.
468            pub fn disable_interrupt(&mut self, interrupt: TimerInterrupt) {
469                match interrupt {
470                    TimerInterrupt::Update => self.regs.dier.modify(|_, w| w.uie().clear_bit()),
471                    // todo: Only DIER is in PAC, or some CCs. PAC BUG? Only avail on some timers/MCUs?
472                    // TimerInterrupt::Trigger => self.regs.dier.modify(|_, w| w.tie().clear_bit()),
473                    // TimerInterrupt::CaptureCompare1 => self.regs.dier.modify(|_, w| w.cc1ie().clear_bit()),
474                    // TimerInterrupt::CaptureCompare2 => self.regs.dier.modify(|_, w| w.cc2ie().clear_bit()),
475                    // TimerInterrupt::CaptureCompare3 => self.regs.dier.modify(|_, w| w.cc3ie().clear_bit()),
476                    // TimerInterrupt::CaptureCompare4 => self.regs.dier.modify(|_, w| w.cc4ie().clear_bit()),
477                    #[cfg(not(feature = "f3"))] // todo: Not working on some variants
478                    TimerInterrupt::UpdateDma => self.regs.dier.modify(|_, w| w.ude().clear_bit()),
479                    // TimerInterrupt::TriggerDma => self.regs.dier.modify(|_, w| w.tde().clear_bit()),
480                    // TimerInterrupt::CaptureCompare1Dma => self.regs.dier.modify(|_, w| w.cc1de().clear_bit()),
481                    // TimerInterrupt::CaptureCompare2Dma => self.regs.dier.modify(|_, w| w.ccd2de().clear_bit()),
482                    // TimerInterrupt::CaptureCompare3Dma => self.regs.dier.modify(|_, w| w.cc3de().clear_bit()),
483                    // TimerInterrupt::CaptureCompare4Dma => self.regs.dier.modify(|_, w| w.cc4de().clear_bit()),
484                    _ => unimplemented!("TODO TEMP PROBLEMS"),
485                }
486            }
487
488            /// Clears interrupt associated with this timer.
489            ///
490            /// If the interrupt is not cleared, it will immediately retrigger after
491            /// the ISR has finished. For examlpe, place this at the top of your timer's
492            /// interrupt handler.
493            pub fn clear_interrupt(&mut self, interrupt: TimerInterrupt) {
494                // Note that unlike other clear interrupt functions, for this, we clear the bit instead
495                // of setting it. Due to the way our SVDs are set up not working well with this atomic clear,
496                // we need to make sure we write 1s to the rest of the bits.
497                // todo: Overcapture flags for each CC? DMA interrupts?
498                unsafe {
499                    match interrupt {
500                        TimerInterrupt::Update => self
501                            .regs
502                            .sr
503                            .write(|w| w.bits(0xffff_ffff).uif().clear_bit()),
504                        // todo: Only DIER is in PAC, or some CCs. PAC BUG? Only avail on some timers?
505                        // TimerInterrupt::Trigger => self.regs.sr.write(|w| w.bits(0xffff_ffff).tif().clear_bit()),
506                        // TimerInterrupt::CaptureCompare1 => self.regs.sr.write(|w| w.bits(0xffff_ffff).cc1if().clear_bit()),
507                        // TimerInterrupt::CaptureCompare2 => self.regs.sr.write(|w| w.bits(0xffff_ffff).cc2if().clear_bit()),
508                        // TimerInterrupt::CaptureCompare3 => self.regs.sr.write(|w| w.bits(0xffff_ffff).cc3if().clear_bit()),
509                        // TimerInterrupt::CaptureCompare4 => self.regs.sr.write(|w| w.bits(0xffff_ffff).cc4if().clear_bit()),
510                        _ => unimplemented!(
511                            "Clearing DMA flags is unimplemented using this function."
512                        ),
513                    }
514                }
515            }
516
517            /// Enable (start) the timer.
518            pub fn enable(&mut self) {
519                self.regs.cr1.modify(|_,w| w.cen().set_bit());
520            }
521
522            /// Disable (stop) the timer.
523            pub fn disable(&mut self) {
524                self.regs.cr1.modify(|_, w| w.cen().clear_bit());
525            }
526
527            /// Check if the timer is enabled.
528            pub fn is_enabled(&self) -> bool {
529                self.regs.cr1.read().cen().bit_is_set()
530            }
531
532            /// Print the (raw) contents of the status register.
533            pub fn read_status(&self) -> u32 {
534                unsafe { self.regs.sr.read().bits() }
535            }
536
537            /// Set the timer frequency, in Hz. Overrides the period or frequency set
538            /// in the constructor.
539            pub fn set_freq(&mut self, mut freq: f32) -> Result<(), ValueError> {
540                assert!(freq > 0.);
541                // todo: Take into account the `timxsw` bit in RCC CFGR3, which may also
542                // todo require an adjustment to freq.
543                match self.cfg.alignment {
544                    Alignment::Edge => (),
545                    _ => freq *= 2.,
546                }
547
548                let (psc, arr) = calc_freq_vals(freq, self.clock_speed)?;
549
550                self.regs.arr.write(|w| unsafe { w.bits(arr.into()) });
551                self.regs.psc.write(|w| unsafe { w.bits(psc.into()) });
552
553                // (PSC+1)*(ARR+1) = TIMclk/Updatefrequency = TIMclk * period
554                // period = (PSC+1)*(ARR+1) / TIMclk
555                // Calculate this based on our actual ARR and PSC values; don't use
556                // the requested frequency or period.
557                let arr_f32 = arr as f32;
558                let period_secs = (psc as f32 + 1.) * ( arr_f32 + 1.) / self.clock_speed as f32;
559                self.ns_per_tick = (period_secs / arr_f32 * 1_000_000_000.) as u64;
560                self.period = period_secs;
561
562                Ok(())
563            }
564
565            /// Set the timer period, in seconds. Overrides the period or frequency set
566            /// in the constructor.
567            pub fn set_period(&mut self, period: f32) -> Result<(), ValueError> {
568                assert!(period > 0.);
569                self.set_freq(1. / period)
570            }
571
572            /// Set the auto-reload register value. Used for adjusting frequency.
573            pub fn set_auto_reload(&mut self, arr: u32) {
574                // todo: Could be u16 or u32 depending on timer resolution,
575                // todo but this works for now.
576                self.regs.arr.write(|w| unsafe { w.bits(arr.into()) });
577            }
578
579            /// Set the prescaler value. Used for adjusting frequency.
580            pub fn set_prescaler(&mut self, psc: u16) {
581                self.regs.psc.write(|w| unsafe { w.bits(psc.into()) });
582            }
583
584            /// Reset the countdown; set the counter to 0.
585            pub fn reset_count(&mut self) {
586                self.regs.cnt.write(|w| unsafe { w.bits(0) });
587            }
588
589            /// UIF Flag in SR register is set when CNT reg is overflow / underflow
590            ///
591            pub fn get_uif(&self ) -> bool {
592                self.regs.sr.read().uif().bit_is_set()
593            }
594
595            pub fn clear_uif(&mut self) {
596                unsafe {
597                    self.regs
598                        .sr
599                        .write(|w| w.bits(0xffff_ffff).uif().clear_bit());
600                }
601            }
602
603            /// Re-initialize the counter and generates an update of the registers. Note that the prescaler
604            /// counter is cleared too (anyway the prescaler ratio is not affected). The counter is cleared.
605            /// When changing timer frequency (or period) via PSC, you may need to run this. Alternatively, change
606            /// the freq in an update ISR.
607            /// Note from RM, PSC reg: PSC contains the value to be loaded in the active prescaler
608            /// register at each update event
609            /// (including when the counter is cleared through UG bit of TIMx_EGR register or through
610            /// trigger controller when configured in “reset mode”).'
611            /// If you're doing something where the updates can wait a cycle, this isn't required. (eg PWM
612            /// with changing duty period).
613            pub fn reinitialize(&mut self) {
614                self.regs.egr.write(|w| w.ug().set_bit());
615                self.clear_interrupt(TimerInterrupt::Update);
616            }
617
618            /// Read the current counter value.
619            pub fn read_count(&self) -> u32 {
620                // todo: This depends on resolution. We read the whole
621                // todo res and pass a u32 just in case.
622                // self.regs.cnt.read().cnt().bits()
623                self.regs.cnt.read().bits()
624            }
625
626
627            /// Enables PWM output for a given channel and output compare, with an initial duty cycle, in Hz.
628            pub fn enable_pwm_output(
629                &mut self,
630                channel: TimChannel,
631                compare: OutputCompare,
632                duty: f32,
633            ) {
634                self.set_capture_compare_output(channel, CaptureCompare::Output);
635                self.set_preload(channel, true);
636                self.set_output_compare(channel, compare);
637                self.set_duty(channel, (self.get_max_duty() as f32 * duty) as $res);
638                self.enable_capture_compare(channel);
639            }
640
641            /// Return the integer associated with the maximum duty period.
642            pub fn get_max_duty(&self) -> $res {
643                #[cfg(feature = "g0")]
644                return self.regs.arr.read().bits().try_into().unwrap();
645                #[cfg(not(feature = "g0"))]
646                self.regs.arr.read().arr().bits().try_into().unwrap()
647            }
648
649             /// See G4 RM, section 29.4.24: Dma burst mode. "The TIMx timers have the capability to
650             /// generate multiple DMA requests upon a single event.
651             /// The main purpose is to be able to re-program part of the timer multiple times without
652             /// software overhead, but it can also be used to read several registers in a row, at regular
653             /// intervals." This may be used to create arbitrary waveforms by modifying the CCR register
654             /// (base address = 13-16, for CCR1-4), or for implementing duty-cycle based digital protocols.
655            #[cfg(not(any(feature = "g0", feature = "f4", feature = "l552", feature = "f3", feature = "l4")))]
656            pub unsafe fn write_dma_burst(
657                &mut self,
658                buf: &[u16],
659                base_address: u8,
660                burst_len: u8,
661                dma_channel: DmaChannel,
662                channel_cfg: ChannelCfg,
663                ds_32_bits: bool,
664                dma_periph: dma::DmaPeriph,
665            ) {
666                // Note: F3 and L4 are unsupported here, since I'm not sure how to select teh
667                // correct Timer channel.
668
669                // todo: Should we disable the timer here?
670
671                let (ptr, len) = (buf.as_ptr(), buf.len());
672
673                // todo: For F3 and L4, manually set channel using PAC for now. Currently
674                // todo we don't have a way here to pick the timer. Could do it with a new macro arg.
675
676                // L44 RM, Table 41. "DMA1 requests for each channel"
677                // #[cfg(any(feature = "f3", feature = "l4"))]
678                // let dma_channel = match tim_channel {
679                //     // SaiChannel::A => DmaInput::Sai1A.dma1_channel(),
680                // };
681                //
682                // #[cfg(feature = "l4")]
683                // match tim_channel {
684                //     SaiChannel::B => dma.channel_select(DmaInput::Sai1B),
685                // };
686
687                // RM:
688                // This example is for the case where every CCRx register has to be updated once. If every
689                // CCRx register is to be updated twice for example, the number of data to transfer should be
690                // 6. Let's take the example of a buffer in the RAM containing data1, data2, data3, data4, data5
691                // and data6. The data is transferred to the CCRx registers as follows: on the first update DMA
692                // request, data1 is transferred to CCR2, data2 is transferred to CCR3, data3 is transferred to
693                // CCR4 and on the second update DMA request, data4 is transferred to CCR2, data5 is
694                // transferred to CCR3 and data6 is transferred to CCR4.
695
696                // 1. Configure the corresponding DMA channel as follows:
697                // –DMA channel peripheral address is the DMAR register address
698                let periph_addr = &self.regs.dmar as *const _ as u32;
699                // –DMA channel memory address is the address of the buffer in the RAM containing
700                // the data to be transferred by DMA into CCRx registers.
701
702                // Number of data to transfer is our buffer len number of registers we're editing, x
703                // number of half-words written to each reg.
704                #[cfg(feature = "h7")]
705                let num_data = len as u32;
706                #[cfg(not(feature = "h7"))]
707                let num_data = len as u16;
708
709                // 2.
710                // Configure the DCR register by configuring the DBA and DBL bit fields as follows:
711                // DBL = 3 transfers, DBA = 0xE.
712
713                // The DBL[4:0] bits in the TIMx_DCR register set the DMA burst length. The timer recognizes
714                // a burst transfer when a read or a write access is done to the TIMx_DMAR address), i.e. the
715                // number of transfers (either in half-words or in bytes).
716                // The DBA[4:0] bits in the TIMx_DCR registers define the DMA base address for DMA
717                // transfers (when read/write access are done through the TIMx_DMAR address). DBA is
718                // defined as an offset starting from the address of the TIMx_CR1 register:
719                // Example:
720                // 00000: TIMx_CR1
721                // 00001: TIMx_CR2
722                // 00010: TIMx_SMCR
723                self.regs.dcr.modify(|_, w| {
724                    w.dba().bits(base_address);
725                    w.dbl().bits(burst_len as u8 - 1)
726                });
727
728                // 3. Enable the TIMx update DMA request (set the UDE bit in the DIER register).
729                // note: Leaving this to application code for now.
730                // self.enable_interrupt(TimerInterrupt::UpdateDma);
731
732                // 4. Enable TIMx
733                self.enable();
734
735                // 5. Enable the DMA channel
736                match dma_periph {
737                    dma::DmaPeriph::Dma1 => {
738                        let mut regs = unsafe { &(*DMA1::ptr()) };
739                        dma::cfg_channel(
740                            &mut regs,
741                            dma_channel,
742                            periph_addr,
743                            ptr as u32,
744                            num_data,
745                            dma::Direction::ReadFromMem,
746                            // Note: This may only be relevant if modifying a reg that changes for 32-bit
747                            // timers, like AAR and CCRx
748                            if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
749                            dma::DataSize::S16,
750                            channel_cfg,
751                        );
752                    }
753                    #[cfg(not(any(feature = "g0", feature = "wb")))]
754                    dma::DmaPeriph::Dma2 => {
755                        let mut regs = unsafe { &(*pac::DMA2::ptr()) };
756                        dma::cfg_channel(
757                            &mut regs,
758                            dma_channel,
759                            periph_addr,
760                            ptr as u32,
761                            num_data,
762                            dma::Direction::ReadFromMem,
763                            // Note: This may only be relevant if modifying a reg that changes for 32-bit
764                            // timers, like AAR and CCRx
765                            if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
766                            dma::DataSize::S16,
767                            channel_cfg,
768                        );
769                    }
770                }
771
772            }
773
774            #[cfg(not(any(feature = "g0", feature = "f4", feature = "l552", feature = "f3", feature = "l4")))]
775            pub unsafe fn read_dma_burst(
776                // todo: Experimenting with input capture.
777                &mut self,
778                buf: &mut [u16],
779                base_address: u8,
780                burst_len: u8,
781                dma_channel: DmaChannel,
782                channel_cfg: ChannelCfg,
783                ds_32_bits: bool,
784                dma_periph: dma::DmaPeriph,
785            ) {
786                let (ptr, len) = (buf.as_mut_ptr(), buf.len());
787
788                let periph_addr = &self.regs.dmar as *const _ as u32;
789
790                #[cfg(feature = "h7")]
791                let num_data = len as u32;
792                #[cfg(not(feature = "h7"))]
793                let num_data = len as u16;
794
795                self.regs.dcr.modify(|_, w| {
796                    w.dba().bits(base_address);
797                    w.dbl().bits(burst_len as u8 - 1)
798                });
799
800                self.enable();
801
802                match dma_periph {
803                    dma::DmaPeriph::Dma1 => {
804                        let mut regs = unsafe { &(*pac::DMA1::ptr()) };
805                        dma::cfg_channel(
806                            &mut regs,
807                            dma_channel,
808                            periph_addr,
809                            ptr as u32,
810                            num_data,
811                            dma::Direction::ReadFromPeriph,
812                            // Note: This may only be relevant if modifying a reg that changes for 32-bit
813                            // timers, like AAR and CCRx
814                            if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
815                            dma::DataSize::S16,
816                            channel_cfg,
817                        );
818                    }
819                    #[cfg(not(any(feature = "g0", feature = "wb")))]
820                    dma::DmaPeriph::Dma2 => {
821                        let mut regs = unsafe { &(*pac::DMA2::ptr()) };
822                        dma::cfg_channel(
823                            &mut regs,
824                            dma_channel,
825                            periph_addr,
826                            ptr as u32,
827                            num_data,
828                            dma::Direction::ReadFromPeriph,
829                            // Note: This may only be relevant if modifying a reg that changes for 32-bit
830                            // timers, like AAR and CCRx
831                            if ds_32_bits { dma::DataSize::S32} else { dma::DataSize::S16 },
832                            dma::DataSize::S16,
833                            channel_cfg,
834                        );
835                    }
836                }
837            }
838
839            /// Get the time elapsed since the start of the timer, taking overflow wraps into account.
840            ///
841            /// Important: the value returned here will only be correct if the ARR and PSC are set
842            /// only using the constructor, `set_freq`, or `set_period` methods.
843            pub fn now(&mut self) -> Instant {
844                // let wrap_count = self.wrap_count;
845                let wrap_count = TICK_OVERFLOW_COUNT.load(Ordering::Acquire);
846
847                let ticks = (self.read_count() as u64 + wrap_count as u64 *
848                    self.get_max_duty() as u64);
849                let count_ns = ticks as i128 * self.ns_per_tick as i128;
850
851                Instant::new(count_ns)
852            }
853
854            pub fn elapsed(&mut self, since: Instant) -> Duration {
855                self.now() - since
856            }
857        }
858
859        #[cfg(feature = "monotonic")]
860        impl Monotonic for Timer<pac::$TIMX> {
861            type Instant = Instant;
862            type Duration = core::time::Duration;
863
864            const DISABLE_INTERRUPT_ON_EMPTY_QUEUE: bool = false;
865
866            fn now(&mut self) -> Self::Instant {
867                self.time_elapsed()
868            }
869
870            /// We use the compare 1 channel for this.
871            /// todo: Support wrapping?
872            fn set_compare(&mut self, instant: Self::Instant) {
873                self.regs
874                    .ccr1()
875                    .write(|w| unsafe { w.ccr().bits(((instant.count_ns as f32 / self.ns_per_tick) as u16).into()) });
876            }
877
878            /// We use the compare 1 channel for this.
879            /// todo: Support wrapping?
880            fn clear_compare_flag(&mut self) {
881                self.regs.sr.modify(|_, w| w.cc1if().clear_bit());
882            }
883
884            fn zero() -> Self::Instant {
885                Instant::default()
886            }
887
888            unsafe fn reset(&mut self) {
889                self.reset_count();
890                TICK_OVERFLOW_COUNT.store(0, Ordering::Release);
891            }
892
893            fn on_interrupt(&mut self) {
894                // self.wrap_count += 1;
895                TICK_OVERFLOW_COUNT.fetch_add(1, Ordering::Relaxed);
896            }
897            fn enable_timer(&mut self) {
898                self.enable();
899            }
900            fn disable_timer(&mut self) {
901                self.disable();
902            }
903
904            /// Print the (raw) contents of the status register.
905            pub fn read_status(&self) -> u32 {
906                unsafe { self.regs.isr.read().bits() }
907            }
908        }
909
910        // #[cfg(feature = "embedded_hal")]
911        // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
912        // impl DelayMs<u32> for Timer<pac::$TIMX> {
913        //     fn delay_ms(&mut self, ms: u32) {
914        //         let ms_to_s = ms as f32 / 1_000.;
915        //         self.set_freq(1. / (ms_to_s)).ok();
916        //         self.reset_count();
917        //         self.enable();
918        //         while self.get_uif() == false {}
919        //         self.clear_uif();
920        //         self.disable();
921        //     }
922        // }
923        //
924        // #[cfg(feature = "embedded_hal")]
925        // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
926        // impl DelayMs<u16> for Timer<pac::$TIMX> {
927        //     fn delay_ms(&mut self, ms: u16) {
928        //         self.delay_ms(ms as u32)
929        //     }
930        // }
931        //
932        // #[cfg(feature = "embedded_hal")]
933        // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
934        // impl DelayMs<u8> for Timer<pac::$TIMX> {
935        //     fn delay_ms(&mut self, ms: u8) {
936        //         self.delay_ms(ms as u32)
937        //     }
938        // }
939        //
940        // #[cfg(feature = "embedded_hal")]
941        // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
942        // impl DelayUs<u32> for Timer<pac::$TIMX> {
943        //     fn delay_us(&mut self, us: u32) {
944        //         let us_to_s = us as f32 / 1_000_000.;
945        //         self.set_freq(1. / (us_to_s)).ok();
946        //         self.reset_count();
947        //         self.enable();
948        //         while self.get_uif() == false {}
949        //         self.clear_uif();
950        //         self.disable();
951        //     }
952        // }
953        //
954        // #[cfg(feature = "embedded_hal")]
955        // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
956        // impl DelayUs<u16> for Timer<pac::$TIMX> {
957        //     fn delay_us(&mut self, us: u16) {
958        //         self.delay_us(us as u32);
959        //     }
960        // }
961        //
962        // #[cfg(feature = "embedded_hal")]
963        // // #[cfg_attr(docsrs, doc(cfg(feature = "embedded_hal")))]
964        // impl DelayUs<u8> for Timer<pac::$TIMX> {
965        //     fn delay_us(&mut self, us: u8) {
966        //         self.delay_us(us as u32);
967        //     }
968        // }
969
970        // /// Implementation of the embedded-hal CountDown trait
971        // /// To use Countdown it is prefered to configure new timer in Oneshot mode :
972        // ///
973        // ///     Example :
974        // ///     llet tim16_conf = TimerConfig {
975        // ///             one_pulse_mode: true,
976        // ///             ..Default::default()
977        // ///         };
978        // ///
979        // ///     Creation of timer. Here the freq arg value is not important, the freq
980        // ///         will be changed for each CountDown start timer depends on delay wanted.
981        // ///
982        // /// let mut tim16: Timer<TIM16> = Timer::new_tim16(dp.TIM16, 1000., tim16_conf, &clocks);
983        // ///
984        // ///
985        // #[cfg(feature = "embedded_hal")]
986        // impl CountDown for Timer<pac::$TIMX>
987        // {
988        //     type Time = duration::Generic<u32>;
989        //
990        //     fn start<T>(&mut self, timeout: T)
991        //         where
992        //             T: Into<Self::Time>,
993        //     {
994        //
995        //         //Disable timer and clear flag uif
996        //         self.disable();
997        //         self.clear_uif();
998        //
999        //         //Get timeout
1000        //         let timeout: Self::Time = timeout.into();
1001        //
1002        //         let denom = timeout.scaling_factor().denominator();
1003        //
1004        //         //Prevent a division by zero
1005        //         if *denom != 0 {
1006        //             //Convert time to seconds
1007        //             let time_to_s = timeout.integer() as f32 / *denom as f32;
1008        //
1009        //             //Configure timer
1010        //             self.set_freq(1. / (time_to_s)).ok();
1011        //             self.reset_count();
1012        //             //Update event to setup prescale and reload registers
1013        //             self.reinitialize();
1014        //             self.clear_uif();
1015        //
1016        //             //start the timer
1017        //             self.enable();
1018        //         }
1019        //
1020        //     }
1021        //
1022        //     /// Wait until the timer has elapsed
1023        //     /// and than clear the event.
1024        //     fn wait(&mut self) -> nb::Result<(), Void> {
1025        //         if !self.get_uif() {
1026        //             Err(nb::Error::WouldBlock)
1027        //         } else {
1028        //             self.clear_uif();
1029        //             self.disable();
1030        //             Ok(())
1031        //         }
1032        //     }
1033        // }
1034    }
1035}
1036
1037// We use macros to support the varying number of capture compare channels available on
1038// different timers.
1039// Note that there's lots of DRY between these implementations.
1040macro_rules! cc_4_channels {
1041    ($TIMX:ident, $res:ident) => {
1042        impl Timer<pac::$TIMX> {
1043            /// Function that allows us to set direction only on timers that have this option.
1044            pub fn set_dir(&mut self) {
1045                self.regs.cr1.modify(|_, w| w.dir().bit(self.cfg.direction as u8 != 0));
1046                self.regs.cr1.modify(|_, w| unsafe { w.cms().bits(self.cfg.alignment as u8) });
1047            }
1048
1049            /// Set up input capture, eg for PWM input.
1050            /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1051            /// Note: Does not handle TISEL (timer input selection register - you must do this manually
1052            /// using the PAC.
1053            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l4x5", feature = "l5", feature = "g0", feature = "wb")))]
1054            pub fn set_input_capture(
1055                &mut self,
1056                channel: TimChannel,
1057                mode: CaptureCompare,
1058                // trigger: InputTrigger,
1059                // slave_mode: InputSlaveMode,
1060                ccp: Polarity,
1061                ccnp: Polarity,
1062            ) {
1063                // 2. Select the active input for TIMx_CCR1: write the CC1S bits to 01 in the TIMx_CCMR1
1064                // register.
1065                self.set_capture_compare_input(channel, mode);
1066
1067                // 1. Select the proper TI1x source (internal or external) with the TI1SEL[3:0] bits in the
1068                // TIMx_TISEL register.
1069                // Leaving it at its default value of 0 selects the timer input, which we'll hard-code
1070                // for now.
1071                // let tisel = 0b0000;
1072
1073                // 3.
1074                // Program the needed input filter duration in relation with the signal connected to the
1075                // timer (when the input is one of the tim_tix (ICxF bits in the TIMx_CCMRx register). Let’s
1076                // imagine that, when toggling, the input signal is not stable during at must 5 internal clock
1077                // cycles. We must program a filter duration longer than these 5 clock cycles. We can
1078                // validate a transition on tim_ti1 when 8 consecutive samples with the new level have
1079                // been detected (sampled at fDTS frequency). Then write IC1F bits to 0011 in the
1080                // TIMx_CCMR1 register.
1081                let filter = 0b0011; // todo experimenting.
1082
1083                match channel {
1084                    TimChannel::C1 => {
1085                        // self.regs.tisel.modify(|_, w| unsafe { w.ti1sel().bits(tisel) });
1086
1087                        // 3. Select the active polarity for TI1FP1 (used both for capture in TIMx_CCR1 and counter
1088                        // clear): write the CC1P and CC1NP bits to ‘0’ (active on rising edge).
1089                        // (Note: We could use the `set_polarity` and `set_complementary_polarity` methods, but
1090                        // this allows us to combine them in a single reg write.)
1091                        self.regs.ccer.modify(|_, w| {
1092                            w.cc1p().bit(ccp.bit());
1093                            w.cc1np().bit(ccnp.bit())
1094                        });
1095
1096                        // 5.
1097                        // Program the input prescaler. In our example, we wish the capture to be performed at
1098                        // each valid transition, so the prescaler is disabled (write IC1PS bits to 00 in the
1099                        // TIMx_CCMR1 register).
1100                        self.regs.ccmr1_input().modify(|_, w| unsafe {
1101                            // todo: PAC ommission?
1102                            // w.ic1psc().bits(0b00);
1103                            w.ic1f().bits(filter)
1104                        });
1105                    }
1106                    TimChannel::C2 => {
1107                        // self.regs.tisel.modify(|_, w| unsafe { w.ti2sel().bits(tisel) });
1108
1109                        self.regs.ccer.modify(|_, w| {
1110                            w.cc2p().bit(ccp.bit());
1111                            w.cc2np().bit(ccnp.bit())
1112                        });
1113
1114                        self.regs.ccmr1_input().modify(|_, w| unsafe {
1115                            w.ic2psc().bits(0b00);
1116                            w.ic2f().bits(filter)
1117                        });
1118                    }
1119                    TimChannel::C3 => {
1120                        // self.regs.tisel.modify(|_, w| unsafe { w.ti3sel().bits(tisel) });
1121
1122                        self.regs.ccer.modify(|_, w| {
1123                            w.cc3p().bit(ccp.bit());
1124                            w.cc3np().bit(ccnp.bit())
1125                        });
1126
1127                        self.regs.ccmr2_input().modify(|_, w| unsafe {
1128                            w.ic3psc().bits(0b00);
1129                            w.ic3f().bits(filter)
1130                        });
1131                    }
1132                    #[cfg(not(feature = "wl"))]
1133                    TimChannel::C4 => {
1134                        // self.regs.tisel.modify(|_, w| unsafe { w.ti4sel().bits(tisel) });
1135
1136                        self.regs.ccer.modify(|_, w| {
1137                            #[cfg(not(any(feature = "f4", feature = "l4")))]
1138                            w.cc4np().bit(ccnp.bit());
1139                            w.cc4p().bit(ccp.bit())
1140                        });
1141
1142                        self.regs.ccmr2_input().modify(|_, w| unsafe {
1143                            w.ic4psc().bits(0b00);
1144                            w.ic4f().bits(filter)
1145                        });
1146                    }
1147                }
1148
1149
1150                // todo: SMCR: Set in the Input PWM settings, but not normal input capture (?)
1151                // 6. Select the valid trigger input: write the TS bits to 101 in the TIMx_SMCR register
1152                // (TI1FP1 selected).
1153                // self.regs.smcr.modify(|_, w| unsafe {
1154                //     w.ts().bits(trigger as u8);
1155                //     // 7. Configure the slave mode controller in reset mode: write the SMS bits to 0100 in the
1156                //     // TIMx_SMCR register.
1157                //     w.sms().bits(slave_mode as u8)
1158                // });
1159
1160                // 6. Enable capture from the counter into the capture register by setting the CC1E bit in the
1161                // TIMx_CCER register.
1162                self.enable_capture_compare(channel);
1163
1164                // 7.If needed, enable the related interrupt request by setting the CC1IE bit in the
1165                // TIMx_DIER register, and/or the DMA request by setting the CC1DE bit in the
1166                // TIMx_DIER register.
1167            }
1168
1169            // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1170
1171            /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1172            pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1173                match channel {
1174                    TimChannel::C1 => {
1175                        self.regs.ccmr1_output().modify(|_, w| unsafe {
1176                            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l5", feature = "wb")))]
1177                            w.oc1m_3().bit((mode as u8) >> 3 != 0);
1178                            w.oc1m().bits((mode as u8) & 0b111)
1179                        });
1180                    }
1181                    TimChannel::C2 => {
1182                        self.regs.ccmr1_output().modify(|_, w| unsafe {
1183                            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l5", feature = "wb")))]
1184                            w.oc2m_3().bit((mode as u8) >> 3 != 0);
1185                            w.oc2m().bits((mode as u8) & 0b111)
1186
1187                        });
1188                    }
1189                    TimChannel::C3 => {
1190                        self.regs.ccmr2_output().modify(|_, w| unsafe {
1191                            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l5", feature = "wb")))]
1192                            w.oc3m_3().bit((mode as u8) >> 3 != 0);
1193                            w.oc3m().bits((mode as u8) & 0b111)
1194
1195                        });
1196                    }
1197                    #[cfg(not(feature = "wl"))]
1198                    TimChannel::C4 => {
1199                        self.regs.ccmr2_output().modify(|_, w| unsafe {
1200                            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l5", feature = "wb", feature = "h7")))]
1201                            w.oc4m_3().bit((mode as u8) >> 3 != 0);
1202                            w.oc4m().bits((mode as u8) & 0b111)
1203
1204                        });
1205                    }
1206                }
1207            }
1208
1209            /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1210            /// to find the portion of the duty cycle used.
1211            pub fn get_duty(&self, channel: TimChannel) -> $res {
1212                cfg_if! {
1213                    if #[cfg(feature = "g0")] {
1214                        match channel {
1215                            TimChannel::C1 => self.regs.ccr1.read().bits(),
1216                            TimChannel::C2 => self.regs.ccr2.read().bits(),
1217                            TimChannel::C3 => self.regs.ccr3.read().bits(),
1218                            #[cfg(not(feature = "wl"))]
1219                            TimChannel::C4 => self.regs.ccr4.read().bits(),
1220                        }
1221                    } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1222                        match channel {
1223                            TimChannel::C1 => self.regs.ccr1.read().ccr1().bits(),
1224                            TimChannel::C2 => self.regs.ccr2.read().ccr2().bits(),
1225                            TimChannel::C3 => self.regs.ccr3.read().ccr3().bits(),
1226                            #[cfg(not(feature = "wl"))]
1227                            TimChannel::C4 => self.regs.ccr4.read().ccr4().bits(),
1228                        }
1229                    } else {
1230                        match channel {
1231                            TimChannel::C1 => self.regs.ccr1().read().ccr().bits().into(),
1232                            TimChannel::C2 => self.regs.ccr2().read().ccr().bits().into(),
1233                            TimChannel::C3 => self.regs.ccr3().read().ccr().bits().into(),
1234                            #[cfg(not(feature = "wl"))]
1235                            TimChannel::C4 => self.regs.ccr4().read().ccr().bits().into(),
1236                        }
1237                    }
1238                }
1239            }
1240
1241            /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1242            /// needs to be re-run if you change ARR at any point.
1243            pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1244                cfg_if! {
1245                    if #[cfg(feature = "g0")] {
1246                        // match channel {
1247                            // TimChannel::C1 => self.regs.ccr1.write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1248                            // TimChannel::C2 => self.regs.ccr2.write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1249                            // TimChannel::C3 => self.regs.ccr3.write(|w| w.ccr3().bits(duty.try_into().unwrap())),
1250                            // TimChannel::C4 => self.regs.ccr4.write(|w| w.ccr4().bits(duty.try_into().unwrap())),
1251                        // };
1252                    } else if #[cfg(any(feature = "l5", feature = "wb", feature = "wl"))] {
1253                        unsafe {
1254                            match channel {
1255                                TimChannel::C1 => self.regs.ccr1.write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1256                                TimChannel::C2 => self.regs.ccr2.write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1257                                TimChannel::C3 => self.regs.ccr3.write(|w| w.ccr3().bits(duty.try_into().unwrap())),
1258                                #[cfg(not(feature = "wl"))]
1259                                TimChannel::C4 => self.regs.ccr4.write(|w| w.ccr4().bits(duty.try_into().unwrap())),
1260                            }
1261                        }
1262                    } else {
1263                        unsafe {
1264                            match channel {
1265                                TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1266                                TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1267                                TimChannel::C3 => self.regs.ccr3().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1268                                #[cfg(not(feature = "wl"))]
1269                                TimChannel::C4 => self.regs.ccr4().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1270                            }
1271                        }
1272                    }
1273                }
1274            }
1275
1276            /// Set timer alignment to Edge, or one of 3 center modes.
1277            /// STM32F303 ref man, section 21.4.1:
1278            /// Bits 6:5 CMS: Center-aligned mode selection
1279            /// 00: Edge-aligned mode. The counter counts up or down depending on the direction bit
1280            /// (DIR).
1281            /// 01: Center-aligned mode 1. The counter counts up and down alternatively. Output compare
1282            /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
1283            /// only when the counter is counting down.
1284            /// 10: Center-aligned mode 2. The counter counts up and down alternatively. Output compare
1285            /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
1286            /// only when the counter is counting up.
1287            /// 11: Center-aligned mode 3. The counter counts up and down alternatively. Output compare
1288            /// interrupt flags of channels configured in output (CCxS=00 in TIMx_CCMRx register) are set
1289            /// both when the counter is counting up or down.
1290            pub fn set_alignment(&mut self, alignment: Alignment) {
1291                self.regs.cr1.modify(|_, w| unsafe { w.cms().bits(alignment as u8) });
1292                self.cfg.alignment = alignment;
1293            }
1294
1295            /// Set output polarity. See docs on the `Polarity` enum.
1296            pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1297                match channel {
1298                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1p().bit(polarity.bit())),
1299                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2p().bit(polarity.bit())),
1300                    TimChannel::C3 => self.regs.ccer.modify(|_, w| w.cc3p().bit(polarity.bit())),
1301                    #[cfg(not(feature = "wl"))]
1302                    TimChannel::C4 => self.regs.ccer.modify(|_, w| w.cc4p().bit(polarity.bit())),
1303                }
1304            }
1305
1306            /// Set complementary output polarity. See docs on the `Polarity` enum.
1307            pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1308                match channel {
1309                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1np().bit(polarity.bit())),
1310                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2np().bit(polarity.bit())),
1311                    TimChannel::C3 => self.regs.ccer.modify(|_, w| w.cc3np().bit(polarity.bit())),
1312                    #[cfg(not(any(feature = "f4", feature = "wl", feature = "l4")))]
1313                    TimChannel::C4 => self.regs.ccer.modify(|_, w| w.cc4np().bit(polarity.bit())),
1314                    #[cfg(any(feature = "f4", feature = "wl", feature = "l4"))] // PAC ommission
1315                    _ => panic!(),
1316                }
1317            }
1318            /// Disables capture compare on a specific channel.
1319            pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1320                match channel {
1321                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1e().clear_bit()),
1322                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2e().clear_bit()),
1323                    TimChannel::C3 => self.regs.ccer.modify(|_, w| w.cc3e().clear_bit()),
1324                    #[cfg(not(feature = "wl"))]
1325                    TimChannel::C4 => self.regs.ccer.modify(|_, w| w.cc4e().clear_bit()),
1326                }
1327            }
1328
1329            /// Enables capture compare on a specific channel.
1330            pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1331                match channel {
1332                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1e().set_bit()),
1333                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2e().set_bit()),
1334                    TimChannel::C3 => self.regs.ccer.modify(|_, w| w.cc3e().set_bit()),
1335                    #[cfg(not(feature = "wl"))]
1336                    TimChannel::C4 => self.regs.ccer.modify(|_, w| w.cc4e().set_bit()),
1337                }
1338            }
1339
1340            /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1341            pub fn set_capture_compare_output(&mut self, channel: TimChannel, mode: CaptureCompare) {
1342                // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1343                self.disable_capture_compare(channel);
1344
1345                match channel {
1346                    TimChannel::C1 => self
1347                        .regs
1348                        .ccmr1_output()
1349                        .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1350                    TimChannel::C2 => self
1351                        .regs
1352                        .ccmr1_output()
1353                        .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1354                    TimChannel::C3 => self
1355                        .regs
1356                        .ccmr2_output()
1357                        .modify(unsafe { |_, w| w.cc3s().bits(mode as u8) }),
1358                    #[cfg(not(feature = "wl"))]
1359                    TimChannel::C4 => self
1360                        .regs
1361                        .ccmr2_output()
1362                        .modify(unsafe { |_, w| w.cc4s().bits(mode as u8) }),
1363                }
1364            }
1365
1366            /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1367            pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1368                // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1369                self.disable_capture_compare(channel);
1370
1371                match channel {
1372                    TimChannel::C1 => self
1373                        .regs
1374                        .ccmr1_input()
1375                        .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1376                    TimChannel::C2 => self
1377                        .regs
1378                        .ccmr1_input()
1379                        .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1380                    TimChannel::C3 => self
1381                        .regs
1382                        .ccmr2_input()
1383                        .modify(unsafe { |_, w| w.cc3s().bits(mode as u8) }),
1384                    #[cfg(not(feature = "wl"))]
1385                    TimChannel::C4 => self
1386                        .regs
1387                        .ccmr2_input()
1388                        .modify(unsafe { |_, w| w.cc4s().bits(mode as u8) }),
1389                }
1390            }
1391
1392            /// Set preload mode.
1393            /// OC1PE: Output Compare 1 preload enable
1394            /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1395            /// new value is taken in account immediately.
1396            /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1397            /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1398            /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1399            /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1400            /// output).
1401            /// 2: The PWM mode can be used without validating the preload register only in one
1402            /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1403            ///
1404            /// Setting preload is required to enable PWM.
1405            pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1406                match channel {
1407                    TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1408                    TimChannel::C2 => self.regs.ccmr1_output().modify(|_, w| w.oc2pe().bit(value)),
1409                    TimChannel::C3 => self.regs.ccmr2_output().modify(|_, w| w.oc3pe().bit(value)),
1410                    #[cfg(not(feature = "wl"))]
1411                    TimChannel::C4 => self.regs.ccmr2_output().modify(|_, w| w.oc4pe().bit(value)),
1412                }
1413
1414                // "As the preload registers are transferred to the shadow registers only when an update event
1415                // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1416                // bit in the TIMx_EGR register."
1417                self.reinitialize();
1418            }
1419        }
1420    }
1421}
1422
1423#[cfg(any(feature = "g0", feature = "g4"))]
1424macro_rules! cc_2_channels {
1425    ($TIMX:ident, $res:ident) => {
1426        impl Timer<pac::$TIMX> {
1427            /// Function that allows us to set direction only on timers that have this option.
1428            fn set_dir(&mut self) {
1429                // self.regs.cr1.modify(|_, w| w.dir().bit(self.cfg.direction as u8 != 0));
1430            }
1431
1432            // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1433
1434            /// Set up input capture, eg for PWM input.
1435            /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1436            /// Note: Does not handle TISEL (timer input selection register - you must do this manually
1437            /// using the PAC.
1438            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l4x5", feature = "l5", feature = "g0")))]
1439            pub fn set_input_capture(
1440                &mut self,
1441                channel: TimChannel,
1442                mode: CaptureCompare,
1443                // trigger: InputTrigger,
1444                // slave_mode: InputSlaveMode,
1445                ccp: Polarity,
1446                ccnp: Polarity,
1447            ) {
1448                self.set_capture_compare_input(channel, mode);
1449
1450                let filter = 0b00;
1451
1452                match channel {
1453                    TimChannel::C1 => {
1454                        self.regs.ccer.modify(|_, w| {
1455                            w.cc1p().bit(ccp.bit());
1456                            w.cc1np().bit(ccnp.bit())
1457                        });
1458
1459                        self.regs.ccmr1_input().modify(|_, w| unsafe {
1460                            // w.ic1psc().bits(0b00);
1461                            w.ic1f().bits(filter)
1462                        });
1463                    }
1464                    TimChannel::C2 => {
1465                        self.regs.ccer.modify(|_, w| {
1466                            w.cc2p().bit(ccp.bit());
1467                            w.cc2np().bit(ccnp.bit())
1468                        });
1469
1470                        self.regs.ccmr1_input().modify(|_, w| unsafe {
1471                            w.ic2psc().bits(0b00);
1472                            w.ic2f().bits(filter)
1473                        });
1474                    }
1475                    _ => panic!()
1476                }
1477
1478                // self.regs.smcr.modify(|_, w| unsafe {
1479                //     w.ts().bits(trigger as u8);
1480                //     w.sms().bits(slave_mode as u8)
1481                // });
1482
1483                self.enable_capture_compare(channel);
1484            }
1485
1486            /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1487            pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1488                match channel {
1489                    TimChannel::C1 => {
1490                       self.regs.ccmr1_output().modify(|_, w| unsafe {
1491                        #[cfg(not(any(feature = "f4", feature = "l5", feature = "wb")))]
1492                           w.oc1m_3().bit((mode as u8) >> 3 != 0);
1493                           w.oc1m().bits((mode as u8) & 0b111)
1494
1495                        });
1496                    }
1497                    TimChannel::C2 => {
1498                      self.regs.ccmr1_output().modify(|_, w| unsafe {
1499                        #[cfg(not(any(feature = "f4", feature = "l5", feature = "wb")))]
1500                          w.oc2m_3().bit((mode as u8) >> 3 != 0);
1501                          w.oc2m().bits((mode as u8) & 0b111)
1502
1503                        });
1504                    }
1505                    _ => panic!()
1506                }
1507            }
1508
1509            /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1510            /// to find the portion of the duty cycle used.
1511            pub fn get_duty(&self, channel: TimChannel) -> $res {
1512                cfg_if! {
1513                    if #[cfg(feature = "g0")] {
1514                        match channel {
1515                            TimChannel::C1 => self.regs.ccr1.read().bits().try_into().unwrap(),
1516                            TimChannel::C2 => self.regs.ccr2.read().bits().try_into().unwrap(),
1517                            _ => panic!()
1518                        }
1519                    } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1520                        match channel {
1521                            TimChannel::C1 => self.regs.ccr1.read().ccr1().bits(),
1522                            TimChannel::C2 => self.regs.ccr2.read().ccr2().bits(),
1523                            _ => panic!()
1524                        }
1525                    } else {
1526                        match channel {
1527                            TimChannel::C1 => self.regs.ccr1().read().ccr().bits().try_into().unwrap(),
1528                            TimChannel::C2 => self.regs.ccr2().read().ccr().bits().try_into().unwrap(),
1529                            _ => panic!()
1530                        }
1531                    }
1532                }
1533            }
1534
1535            /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1536            /// needs to be re-run if you change ARR at any point.
1537            pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1538                cfg_if! {
1539                    if #[cfg(feature = "g0")] {
1540                        match channel {
1541                            // TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1542                            // TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1543                            _ => panic!()
1544                        };
1545                    } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1546                        unsafe {
1547                            match channel {
1548                                TimChannel::C1 => self.regs.ccr1.write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1549                                TimChannel::C2 => self.regs.ccr2.write(|w| w.ccr2().bits(duty.try_into().unwrap())),
1550                                _ => panic!()
1551                            }
1552                        }
1553                    } else {
1554                        unsafe {
1555                            match channel {
1556                                TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1557                                TimChannel::C2 => self.regs.ccr2().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1558                                _ => panic!()
1559                            }
1560                        }
1561                    }
1562                }
1563            }
1564
1565            /// Set output polarity. See docs on the `Polarity` enum.
1566            pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1567                match channel {
1568                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1p().bit(polarity.bit())),
1569                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2p().bit(polarity.bit())),
1570                    _ => panic!()
1571                }
1572            }
1573
1574            /// Set complementary output polarity. See docs on the `Polarity` enum.
1575            pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1576                match channel {
1577                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1np().bit(polarity.bit())),
1578                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2np().bit(polarity.bit())),
1579                    _ => panic!()
1580                }
1581            }
1582            /// Disables capture compare on a specific channel.
1583            pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1584                match channel {
1585                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1e().clear_bit()),
1586                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2e().clear_bit()),
1587                    _ => panic!()
1588                }
1589            }
1590
1591            /// Enables capture compare on a specific channel.
1592            pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1593                match channel {
1594                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1e().set_bit()),
1595                    TimChannel::C2 => self.regs.ccer.modify(|_, w| w.cc2e().set_bit()),
1596                    _ => panic!()
1597                }
1598            }
1599
1600            /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1601            pub fn set_capture_compare_output(&mut self, channel: TimChannel, mode: CaptureCompare) {
1602                self.disable_capture_compare(channel);
1603
1604                match channel {
1605                    TimChannel::C1 => self
1606                        .regs
1607                        .ccmr1_output()
1608                        .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1609                    TimChannel::C2 => self
1610                        .regs
1611                        .ccmr1_output()
1612                        .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1613                    _ => panic!()
1614                }
1615            }
1616
1617            /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1618            pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1619                self.disable_capture_compare(channel);
1620
1621                match channel {
1622                    // Note: CC1S bits are writable only when the channel is OFF (CC1E = 0 in TIMx_CCER)
1623                    TimChannel::C1 => self
1624                        .regs
1625                        .ccmr1_input()
1626                        .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1627
1628                    TimChannel::C2 => self
1629                        .regs
1630                        .ccmr1_input()
1631                        .modify(unsafe { |_, w| w.cc2s().bits(mode as u8) }),
1632                        _ => panic!()
1633                }
1634            }
1635
1636            /// Set preload mode.
1637            /// OC1PE: Output Compare 1 preload enable
1638            /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1639            /// new value is taken in account immediately.
1640            /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1641            /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1642            /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1643            /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1644            /// output).
1645            /// 2: The PWM mode can be used without validating the preload register only in one
1646            /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1647            ///
1648            /// Setting preload is required to enable PWM.
1649            pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1650                match channel {
1651                    TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1652                    TimChannel::C2 => self.regs.ccmr1_output().modify(|_, w| w.oc2pe().bit(value)),
1653                    _ => panic!()
1654                }
1655
1656                // "As the preload registers are transferred to the shadow registers only when an update event
1657                // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1658                // bit in the TIMx_EGR register."
1659                self.reinitialize();
1660            }
1661
1662        }
1663    }
1664}
1665
1666macro_rules! cc_1_channel {
1667    ($TIMX:ident, $res:ident) => {
1668        impl Timer<pac::$TIMX> {
1669            /// Function that allows us to set direction only on timers that have this option.
1670            fn set_dir(&mut self) {} // N/A with these 1-channel timers.
1671
1672            // todo: more advanced PWM modes. Asymmetric, combined, center-aligned etc.
1673
1674            /// Set up input capture, eg for PWM input.
1675            /// L4 RM, section 26.3.8. H723 RM, section 43.3.7.
1676            /// Note: Does not handle TISEL (timer input selection register - you must do this manually
1677            /// using the PAC.
1678            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l4x5", feature = "l5", feature = "g0")))]
1679            pub fn set_input_capture(
1680                &mut self,
1681                channel: TimChannel,
1682                mode: CaptureCompare,
1683                // trigger: InputTrigger,
1684                // slave_mode: InputSlaveMode,
1685                ccp: Polarity,
1686                ccnp: Polarity,
1687            ) {
1688                self.set_capture_compare_input(channel, mode);
1689
1690                let filter = 0b00;
1691
1692                match channel {
1693                    TimChannel::C1 => {
1694                        self.regs.ccer.modify(|_, w| {
1695                            w.cc1p().bit(ccp.bit());
1696                            w.cc1np().bit(ccnp.bit())
1697                        });
1698
1699                        self.regs.ccmr1_input().modify(|_, w| unsafe {
1700                            w.ic1psc().bits(0b00);
1701                            w.ic1f().bits(filter)
1702                        });
1703                    }
1704                    _ => panic!()
1705                }
1706
1707                // todo?
1708                // self.regs.smcr.modify(|_, w| unsafe {
1709                //     w.ts().bits(trigger as u8);
1710                //     w.sms().bits(slave_mode as u8)
1711                // });
1712
1713                self.enable_capture_compare(channel);
1714            }
1715
1716            /// Set Output Compare Mode. See docs on the `OutputCompare` enum.
1717            pub fn set_output_compare(&mut self, channel: TimChannel, mode: OutputCompare) {
1718                match channel {
1719                    TimChannel::C1 => {
1720                        #[cfg(not(feature = "g070"))] // todo: PAC bug?
1721                        self.regs.ccmr1_output().modify(|_, w| unsafe {
1722                            // todo: L5/WB is probably due to a PAC error. Has oc1m_2.
1723                            #[cfg(not(any(feature = "f3", feature = "f4", feature = "l4",
1724                                feature = "l5", feature = "wb", feature = "g0")))]
1725                            w.oc1m_3().bit((mode as u8) >> 3 != 0);
1726                            w.oc1m().bits((mode as u8) & 0b111)
1727                        });
1728                    }
1729                    _ => panic!()
1730                }
1731            }
1732
1733            /// Return the set duty period for a given channel. Divide by `get_max_duty()`
1734            /// to find the portion of the duty cycle used.
1735            pub fn get_duty(&self, channel: TimChannel) -> $res {
1736                cfg_if! {
1737                    if #[cfg(feature = "g0")] {
1738                        match channel {
1739                            // todo: This isn't right!!
1740                            // todo: PAC is showing G0 having Tim15 as 32 bits. Is this right?
1741                            TimChannel::C1 => self.regs.ccr1.read().bits().try_into().unwrap(),
1742                            _ => panic!()
1743                        }
1744                    } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1745                        match channel {
1746                            TimChannel::C1 => self.regs.ccr1.read().ccr1().bits(),
1747                            _ => panic!()
1748                        }
1749                    } else {
1750                        match channel {
1751                            TimChannel::C1 => self.regs.ccr1().read().ccr().bits().try_into().unwrap(),
1752                            _ => panic!()
1753                        }
1754                    }
1755                }
1756            }
1757
1758            /// Set the duty cycle, as a portion of ARR (`get_max_duty()`). Note that this
1759            /// needs to be re-run if you change ARR at any point.
1760            pub fn set_duty(&mut self, channel: TimChannel, duty: $res) {
1761                cfg_if! {
1762                    if #[cfg(feature = "g0")] {
1763                        match channel {
1764                            // todo: This isn't right!!
1765                            TimChannel::C1 => self.regs.ccr1.read().bits(),
1766                            _ => panic!()
1767                        };
1768                    } else if #[cfg(any(feature = "wb", feature = "wl", feature = "l5"))] {
1769                        unsafe {
1770                            match channel {
1771                                TimChannel::C1 => self.regs.ccr1.write(|w| w.ccr1().bits(duty.try_into().unwrap())),
1772                                _ => panic!()
1773                            }
1774                        }
1775                    } else {
1776                        unsafe {
1777                            match channel {
1778                                TimChannel::C1 => self.regs.ccr1().write(|w| w.ccr().bits(duty.try_into().unwrap())),
1779                                _ => panic!()
1780                            }
1781                        }
1782                    }
1783                }
1784            }
1785
1786            /// Set output polarity. See docs on the `Polarity` enum.
1787            pub fn set_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1788                match channel {
1789                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1p().bit(polarity.bit())),
1790                    _ => panic!()
1791                }
1792            }
1793
1794            /// Set complementary output polarity. See docs on the `Polarity` enum.
1795            pub fn set_complementary_polarity(&mut self, channel: TimChannel, polarity: Polarity) {
1796                match channel {
1797                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1np().bit(polarity.bit())),
1798                    _ => panic!()
1799                }
1800            }
1801            /// Disables capture compare on a specific channel.
1802            pub fn disable_capture_compare(&mut self, channel: TimChannel) {
1803                match channel {
1804                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1e().clear_bit()),
1805                    _ => panic!()
1806                }
1807            }
1808
1809            /// Enables capture compare on a specific channel.
1810            pub fn enable_capture_compare(&mut self, channel: TimChannel) {
1811                match channel {
1812                    TimChannel::C1 => self.regs.ccer.modify(|_, w| w.cc1e().set_bit()),
1813                    _ => panic!()
1814                }
1815            }
1816
1817            /// Set Capture Compare mode in output mode. See docs on the `CaptureCompare` enum.
1818            pub fn set_capture_compare_output(&mut self, channel: TimChannel, mode: CaptureCompare) {
1819                self.disable_capture_compare(channel);
1820
1821                match channel {
1822                    TimChannel::C1 => self
1823                        .regs
1824                        .ccmr1_output()
1825                        .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1826                    _ => panic!()
1827                }
1828            }
1829
1830           /// Set Capture Compare mode in input mode. See docs on the `CaptureCompare` enum.
1831            pub fn set_capture_compare_input(&mut self, channel: TimChannel, mode: CaptureCompare) {
1832                self.disable_capture_compare(channel);
1833
1834                match channel {
1835                    TimChannel::C1 => self
1836                        .regs
1837                        .ccmr1_input()
1838                        .modify(unsafe { |_, w| w.cc1s().bits(mode as u8) }),
1839                    _ => panic!()
1840                }
1841            }
1842
1843            /// Set preload mode.
1844            /// OC1PE: Output Compare 1 preload enable
1845            /// 0: Preload register on TIMx_CCR1 disabled. TIMx_CCR1 can be written at anytime, the
1846            /// new value is taken in account immediately.
1847            /// 1: Preload register on TIMx_CCR1 enabled. Read/Write operations access the preload
1848            /// register. TIMx_CCR1 preload value is loaded in the active register at each update event.
1849            /// Note: 1: These bits can not be modified as long as LOCK level 3 has been programmed
1850            /// (LOCK bits in TIMx_BDTR register) and CC1S=’00’ (the channel is configured in
1851            /// output).
1852            /// 2: The PWM mode can be used without validating the preload register only in one
1853            /// pulse mode (OPM bit set in TIMx_CR1 register). Else the behavior is not guaranteed.
1854            ///
1855            /// Setting preload is required to enable PWM.
1856            pub fn set_preload(&mut self, channel: TimChannel, value: bool) {
1857                match channel {
1858                    TimChannel::C1 => self.regs.ccmr1_output().modify(|_, w| w.oc1pe().bit(value)),
1859                    _ => panic!()
1860                }
1861
1862                // "As the preload registers are transferred to the shadow registers only when an update event
1863                // occurs, before starting the counter, you have to initialize all the registers by setting the UG
1864                // bit in the TIMx_EGR register."
1865                self.reinitialize();
1866            }
1867        }
1868    }
1869}
1870
1871/// Calculate values required to set the timer frequency: `PSC` and `ARR`. This can be
1872/// used for initial timer setup, or changing the value later. If used in performance-sensitive
1873/// code or frequently, set ARR and PSC directly instead of using this.
1874fn calc_freq_vals(freq: f32, clock_speed: u32) -> Result<(u16, u16), ValueError> {
1875    // `period` and `clock_speed` are both in Hz.
1876
1877    // PSC and ARR range: 0 to 65535
1878    // (PSC+1)*(ARR+1) = TIMclk/Updatefrequency = TIMclk * period
1879    // APB1 (pclk1) is used by Tim2, 3, 4, 6, 7.
1880    // APB2 (pclk2) is used by Tim8, 15-20 etc.
1881
1882    // We need to factor the right-hand-side of the above equation
1883    // into integers. There are likely clever algorithms available to do this.
1884    // Some examples: https://cp-algorithms.com/algebra/factorization.html
1885    // We've chosen something that attempts to maximize ARR, for precision when
1886    // setting duty cycle. Alternative approaches might involve setting a frequency closest to the
1887    // requested one.
1888
1889    // If you work with pure floats, there are an infinite number of solutions: Ie for any value of PSC,
1890    // you can find an ARR to solve the equation.
1891    // The actual values are integers that must be between 0 and 65_536
1892    // Different combinations will result in different amounts of rounding error.
1893
1894    let max_val = 65_535.;
1895    let rhs = clock_speed as f32 / freq;
1896
1897    let psc = ((rhs - 1.) / (1 << 16) as f32).round();
1898    let arr = rhs / (psc + 1.) - 1.;
1899
1900    if arr > max_val || psc > max_val {
1901        return Err(ValueError {});
1902    }
1903
1904    Ok((psc as u16, arr as u16))
1905}
1906
1907cfg_if! {
1908    if #[cfg(not(any(
1909        feature = "f401",
1910        feature = "f410",
1911        feature = "f411",
1912        feature = "f413",
1913        feature = "g031",
1914        feature = "g041",
1915        feature = "g070",
1916        feature = "g030",
1917        feature = "wb",
1918        feature = "wl"
1919    )))]  {
1920        /// Represents a Basic timer, used primarily to trigger the onboard DAC. Eg Tim6 or Tim7.
1921        pub struct BasicTimer<R> {
1922            pub regs: R,
1923            clock_speed: u32,
1924        }
1925
1926        impl<R> BasicTimer<R>
1927            where
1928                R: Deref<Target = pac::tim6::RegisterBlock> + RccPeriph,
1929        {
1930            /// Initialize a Basic timer, including  enabling and resetting
1931            /// its RCC peripheral clock.
1932            pub fn new(
1933                regs: R,
1934                freq: f32,
1935                clock_cfg: &Clocks,
1936            ) -> Self {
1937                let rcc = unsafe { &(*RCC::ptr()) };
1938                R::en_reset(rcc);
1939
1940                // Self { regs, config, clock_speed: clocks.apb1_timer()  }
1941                let mut result = Self { regs, clock_speed: clock_cfg.apb1_timer()  };
1942
1943                result.set_freq(freq).ok();
1944                result
1945            }
1946
1947            // todo: These fns are DRY from GP timer code!
1948
1949            /// Enable the timer.
1950            pub fn enable(&mut self) {
1951                self.regs.cr1.modify(|_, w| w.cen().set_bit());
1952            }
1953
1954            /// Disable the timer.
1955            pub fn disable(&mut self) {
1956                self.regs.cr1.modify(|_, w| w.cen().clear_bit());
1957            }
1958
1959            /// Check if the timer is enabled.
1960            pub fn is_enabled(&self) -> bool {
1961                self.regs.cr1.read().cen().bit_is_set()
1962            }
1963
1964            /// Set the timer period, in seconds. Overrides the period or frequency set
1965            /// in the constructor.  If changing pe riod frequently, don't use this method, as
1966            /// it has computational overhead: use `set_auto_reload` and `set_prescaler` methods instead.
1967            pub fn set_period(&mut self, time: f32) -> Result<(), ValueError> {
1968                assert!(time > 0.);
1969                self.set_freq(1. / time)
1970            }
1971
1972            /// Set the timer frequency, in Hz. Overrides the period or frequency set
1973            /// in the constructor. If changing frequency frequently, don't use this method, as
1974            /// it has computational overhead: use `set_auto_reload` and `set_prescaler` methods instead.
1975            pub fn set_freq(&mut self, freq: f32) -> Result<(), ValueError> {
1976                assert!(freq > 0.);
1977
1978                let (psc, arr) = calc_freq_vals(freq, self.clock_speed)?;
1979
1980                self.regs.arr.write(|w| unsafe { w.bits(arr.into()) });
1981                self.regs.psc.write(|w| unsafe { w.bits(psc.into()) });
1982
1983                Ok(())
1984            }
1985
1986            /// Return the integer associated with the maximum duty period.
1987            pub fn get_max_duty(&self) -> u16 {
1988                #[cfg(feature = "l5")]
1989                return self.regs.arr.read().bits() as u16;
1990                #[cfg(not(feature = "l5"))]
1991                self.regs.arr.read().arr().bits()
1992            }
1993
1994            /// Set the auto-reload register value. Used for adjusting frequency.
1995            pub fn set_auto_reload(&mut self, arr: u16) {
1996                self.regs.arr.write(|w| unsafe { w.bits(arr.into()) });
1997            }
1998
1999            /// Set the prescaler value. Used for adjusting frequency.
2000            pub fn set_prescaler(&mut self, psc: u16) {
2001                self.regs.psc.write(|w| unsafe { w.bits(psc.into()) });
2002            }
2003
2004            /// Reset the count; set the counter to 0.
2005            pub fn reset_count(&mut self) {
2006                self.regs.cnt.write(|w| unsafe { w.bits(0) });
2007            }
2008
2009            /// Read the current counter value.
2010            pub fn read_count(&self) -> u16 {
2011                #[cfg(feature = "l5")]
2012                return self.regs.cnt.read().bits() as u16;
2013                #[cfg(not(feature = "l5"))]
2014                self.regs.cnt.read().cnt().bits()
2015            }
2016
2017            /// Allow selected information to be sent in master mode to slave timers for
2018            /// synchronization (TRGO).
2019            pub fn set_mastermode(&self, mode: MasterModeSelection) {
2020                self.regs.cr2.modify(|_, w| unsafe { w.mms().bits(mode as u8) });
2021            }
2022        }
2023    }
2024}
2025
2026/// A freestanding function that does not require access to a `Timer` struct. Clears the Update interrupt.
2027pub fn clear_update_interrupt(tim_num: u8) {
2028    unsafe {
2029        let periphs = pac::Peripherals::steal();
2030
2031        // todo: This is likely to fail on some variants, and it's missing a number of timer periphs.
2032
2033        let bits = 0xffff_ffff;
2034
2035        match tim_num {
2036            #[cfg(not(any(feature = "f373")))]
2037            1 => periphs.TIM1.sr.write(|w| w.bits(bits).uif().clear_bit()),
2038            #[cfg(not(any(
2039                 feature = "f410",
2040                 feature = "g070",
2041                 feature = "l5", // todo PAC bug?
2042                 feature = "wb55", // todo PAC bug?
2043            )))]
2044            2 => periphs.TIM2.sr.write(|w| w.bits(bits).uif().clear_bit()),
2045            #[cfg(not(any(
2046                feature = "f301",
2047                feature = "l4x1",
2048                // feature = "l412",
2049                feature = "l5", // todo PAC bug?
2050                feature = "l4x3",
2051                feature = "f410",
2052                feature = "wb",
2053                feature = "wl"
2054            )))]
2055            3 => periphs.TIM3.sr.write(|w| w.bits(bits).uif().clear_bit()),
2056            #[cfg(not(any(
2057                feature = "f301",
2058                feature = "f3x4",
2059                feature = "f410",
2060                feature = "l4x1",
2061                feature = "l4x2",
2062                feature = "l412",
2063                feature = "l4x3",
2064                feature = "l5", // todo PAC bug?
2065                feature = "g0",
2066                feature = "wb",
2067                feature = "wl"
2068            )))]
2069            4 => periphs.TIM4.sr.write(|w| w.bits(bits).uif().clear_bit()),
2070            #[cfg(any(
2071                feature = "f373",
2072                feature = "l4x5",
2073                feature = "l4x6",
2074            // feature = "l562", // todo: PAC bug?
2075                feature = "h5",
2076                feature = "h7",
2077                feature = "g473",
2078                feature = "g474",
2079                feature = "g483",
2080                feature = "g484",
2081                all(feature = "f4", not(feature = "f410")),
2082            ))]
2083            5 => periphs.TIM5.sr.write(|w| w.bits(bits).uif().clear_bit()),
2084            _ => unimplemented!(),
2085        }
2086    };
2087}
2088
2089// /// Experimental approach where we set frequency without taking ownership.
2090// pub fn set_freq(timer: TimerNum, mut freq: f32) -> Result<(), ValueError> {
2091//
2092// }
2093
2094// todo: Non-macro refactor base timer reg blocks:
2095
2096// GP 32-bit: Tim2
2097// 2, 3, 4, 5
2098
2099// GP 16-bit:
2100// 15, 16, 17 // (9-14 on F4) 14 on G0
2101
2102// Basic:
2103// 6, 7
2104
2105// Advanced: 1/8/20
2106
2107#[cfg(not(any(feature = "f373")))]
2108make_timer!(TIM1, tim1, 2, u16);
2109
2110#[cfg(not(any(feature = "f373", feature = "g0", feature = "g4")))]
2111cc_4_channels!(TIM1, u16);
2112// todo: PAC error?
2113// TIM1 on G4 is nominally 16-bits, but has ~20 bits on ARR, with PAC showing 32 bits?
2114#[cfg(any(feature = "g0", feature = "g4"))]
2115cc_2_channels!(TIM1, u16);
2116
2117cfg_if! {
2118    if #[cfg(not(any(
2119        feature = "f410",
2120        feature = "g070",
2121        feature = "l5", // todo PAC bug?
2122        feature = "wb55", // todo PAC bug?
2123    )))] {
2124        make_timer!(TIM2, tim2, 1, u32);
2125        cc_4_channels!(TIM2, u32);
2126    }
2127}
2128
2129// todo: Note. G4, for example, has TIM2 and 5 as 32-bit, and TIM3 and 4 as 16-bit per RM,
2130// todo: But PAC shows different.
2131cfg_if! {
2132    if #[cfg(not(any(
2133        feature = "f301",
2134        feature = "l4x1",
2135        // feature = "l412",
2136        feature = "l5", // todo PAC bug?
2137        feature = "l4x3",
2138        feature = "f410",
2139        feature = "wb",
2140        feature = "wl"
2141    )))] {
2142        make_timer!(TIM3, tim3, 1, u32);
2143        cc_4_channels!(TIM3, u32);
2144    }
2145}
2146
2147cfg_if! {
2148    if #[cfg(not(any(
2149        feature = "f301",
2150        feature = "f3x4",
2151        feature = "f410",
2152        feature = "l4x1",
2153        feature = "l4x2",
2154        feature = "l412",
2155        feature = "l4x3",
2156        feature = "l5", // todo PAC bug?
2157        feature = "g0",
2158        feature = "wb",
2159        feature = "wl"
2160    )))] {
2161        make_timer!(TIM4, tim4, 1, u32);
2162        cc_4_channels!(TIM4, u32);
2163    }
2164}
2165
2166cfg_if! {
2167    if #[cfg(any(
2168       feature = "f373",
2169       feature = "l4x5",
2170       feature = "l4x6",
2171       // feature = "l562", // todo: PAC bug?
2172       feature = "h5",
2173       feature = "h7",
2174       feature = "g473",
2175       feature = "g474",
2176       feature = "g483",
2177       feature = "g484",
2178       all(feature = "f4", not(feature = "f410")),
2179   ))] {
2180        make_timer!(TIM5, tim5, 1, u32);
2181        cc_4_channels!(TIM5, u32);
2182   }
2183}
2184
2185cfg_if! {
2186    if #[cfg(any(
2187        feature = "f303",
2188        feature = "l4x5",
2189        feature = "l4x6",
2190        feature = "l562",
2191        feature = "h5",
2192        feature = "h7",
2193    ))] {
2194        make_timer!(TIM8, tim8, 2, u16);
2195        // todo: Some issues with field names or something on l562 here.
2196        #[cfg(not(feature = "l5"))] // PAC bug.
2197        cc_4_channels!(TIM8, u16);
2198        #[cfg(feature = "l5")] // PAC bug.
2199        cc_1_channel!(TIM8, u16);
2200    }
2201}
2202
2203// todo: G4 should be 16-bits for TIM8. Why does the PAC use 32?
2204cfg_if! {
2205    if #[cfg(feature = "g4")] {
2206        make_timer!(TIM8, tim8, 2, u32);
2207        cc_4_channels!(TIM8, u32);
2208    }
2209}
2210
2211cfg_if! {
2212    if #[cfg(feature = "h5")] {
2213        make_timer!(TIM12, tim12, 1, u32);
2214        cc_2_channels!(TIM12, u32);
2215
2216        make_timer!(TIM13, tim13, 1, u32);
2217        cc_2_channels!(TIM13, u32);
2218
2219        make_timer!(TIM14, tim14, 1, u32);
2220        cc_2_channels!(TIM14, u32);
2221    }
2222}
2223
2224// Todo: the L5 PAC has an address error on TIM15 - remove it until solved.
2225cfg_if! {
2226    if #[cfg(not(any(
2227        feature = "l5",
2228        feature = "f4",
2229        feature = "g031",
2230        feature = "g031",
2231        feature = "g041",
2232        feature = "g030",
2233        feature = "wb",
2234        feature = "wl"
2235    )))] {
2236        make_timer!(TIM15, tim15, 2, u16);
2237        // todo: TIM15 on some variant has 2 channels (Eg H7). On others, like L4x3, it appears to be 1.
2238        cc_1_channel!(TIM15, u16);
2239    }
2240}
2241
2242#[cfg(not(feature = "f4"))]
2243make_timer!(TIM16, tim16, 2, u16);
2244#[cfg(not(feature = "f4"))]
2245cc_1_channel!(TIM16, u16);
2246
2247cfg_if! {
2248    if #[cfg(not(any(
2249        feature = "l4x1",
2250        feature = "l4x2",
2251        feature = "l412",
2252        feature = "l4x3",
2253        feature = "f4",
2254    )))] {
2255        make_timer!(TIM17, tim17, 2, u16);
2256        cc_1_channel!(TIM17, u16);
2257    }
2258}
2259
2260// { todo: tim18
2261//     TIM18: (tim18, apb2, enr, rstr),
2262// },
2263
2264cfg_if! {
2265    if #[cfg(any(feature = "f373"))] {
2266        make_timer!(TIM12, tim12, 1, u16);
2267        make_timer!(TIM13, tim13, 1, u16);
2268        make_timer!(TIM14, tim14, 1, u16);
2269        make_timer!(TIM19, tim19, 2, u16);
2270
2271        cc_1_channel!(TIM12, u16);
2272        cc_1_channel!(TIM13, u16);
2273        cc_1_channel!(TIM14, u16);
2274        cc_1_channel!(TIM19, u16);
2275    }
2276}
2277
2278// todo: G4 (maybe not all variants?) have TIM20.
2279#[cfg(any(feature = "f303"))]
2280make_timer!(TIM20, tim20, 2, u16);
2281#[cfg(any(feature = "f303"))]
2282cc_4_channels!(TIM20, u16);
2283
2284// todo: Remove the final "true/false" for adv ctrl. You need a sep macro like you do for ccx_channel!.