atsamd_hal/peripherals/clock/d5x/v2/
gclk.rs

1//! # Generic Clock Controllers
2//!
3//! ## Overview
4//!
5//! The generic clock controller is central to the clocking system in ATSAMD
6//! chips. It provides 12 generic clock generators to modify and distribute
7//! clocks to other peripherals. Within the clock tree, these clock generators
8//! act as the branch clocks, connecting internal or external root or branch
9//! clocks to other branch or leaf clocks.
10//!
11//! Each clock generator takes an input clock, optionally divides it, and
12//! produces an output clock. The input clock can be:
13//!
14//! - A GPIO input ([`Pin`])
15//! - An external crystal oscillator ([`Xosc`])
16//! - An external 32 kHz oscillator ([`Xosc32k`])
17//! - The ultra-low power 32 kHz oscillator ([`OscUlp32k`])
18//! - The 48 MHz DFLL ([`Dfll`])
19//! - A DPLL ([`Dpll`])
20//! - Generic clock generator #1 ([`Gclk1`])
21//!
22//! The output clock can be:
23//! - A peripheral channel clock ([`Pclk`])
24//! - A GPIO pin ([`GclkOut`])
25//!
26//! ## Example
27//!
28//! The configuration of a [`Gclk`] is best shown with an example. However, the
29//! example assumes you are already familiar with the basics of the `clock`
30//! module. See the [`clock` module documentation](super) for an overview.
31//!
32//! Suppose we start with the default clock tree after power-on reset.
33//!
34//! ```text
35//! DFLL (48 MHz)
36//! └── GCLK0 (48 MHz)
37//!     └── Main clock (48 MHz)
38//! ```
39//!
40//! We would like to transform it to a clock tree like this:
41//!
42//! ```text
43//! DFLL (48 MHz)
44//! └── GCLK0 (48 MHz)
45//!     └── Main clock (48 MHz)
46//!
47//! GCLK_IN1 (PB14, 24 MHz)
48//! └── GCLK1 (12 MHz)
49//!     ├── SERCOM0
50//!     └── GCLK2 (3 MHz)
51//!         ├── SERCOM1
52//!         └── GCLK_OUT2 (PA16, 3 MHz)
53//! ```
54//!
55//! Let's start by using [`clock_system_at_reset`] to access the HAL clocking
56//! structs. We will also need access to the [`gpio`] [`Pins`].
57//!
58//! ```no_run
59//! use atsamd_hal::{
60//!     clock::v2::{
61//!         clock_system_at_reset,
62//!         gclk::{Gclk, GclkDiv8, GclkDiv16},
63//!         pclk::Pclk,
64//!     },
65//!     gpio::Pins,
66//!     pac::Peripherals,
67//!     fugit::RateExtU32,
68//! };
69//! let mut pac = Peripherals::take().unwrap();
70//! let (mut buses, clocks, tokens) = clock_system_at_reset(
71//!     pac.oscctrl,
72//!     pac.osc32kctrl,
73//!     pac.gclk,
74//!     pac.mclk,
75//!     &mut pac.nvmctrl,
76//! );
77//! let pins = Pins::new(pac.port);
78//! ```
79//!
80//! Next, we use [`Gclk::from_pin`] to create a [`Gclk`] from a [`GclkToken`],
81//! GPIO [`Pin`] and frequency, in [`Hertz`]. In this case, we create an
82//! instance of [`Gclk1`].
83//!
84//! At this point, notice that [`Gclk<G, I>`] takes two type parameters. `G` is
85//! a [`GclkId`] identifying which of the 12 generators this `Gclk` represents.
86//! [`Gclk1<I>`] is simply an alias for `Gclk<Gclk1Id, I>`. `I` is an
87//! [`Id` type](super#id-types) identifying the input clock, which must be a
88//! valid [`GclkSourceId`]. In this case, `I` is [`PB14`](gpio::PB14), which is
89//! a `GclkSourceId` for `Gclk1`, because it implements [`GclkIo`] with
90//! [`GclkIo::GclkId`]` = Gclk1Id`.
91//!
92//! ```no_run
93//! # use atsamd_hal::{
94//! #     clock::v2::{
95//! #         clock_system_at_reset,
96//! #         gclk::{Gclk, GclkDiv8, GclkDiv16},
97//! #         pclk::Pclk,
98//! #     },
99//! #     gpio::Pins,
100//! #     pac::Peripherals,
101//! #     fugit::RateExtU32,
102//! # };
103//! # let mut pac = Peripherals::take().unwrap();
104//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
105//! #     pac.oscctrl,
106//! #     pac.osc32kctrl,
107//! #     pac.gclk,
108//! #     pac.mclk,
109//! #     &mut pac.nvmctrl,
110//! # );
111//! # let pins = Pins::new(pac.port);
112//! let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
113//! ```
114//!
115//! While we have created a [`Gclk`], we have not yet enabled it. But before
116//! doing so, we would like to set the divider to reduce the input frequency of
117//! 24 MHz to a 12 MHz output. We call `Gclk::div`, which uses a builder API, so
118//! that it can be chained with the call to `Gclk::enable`.
119//!
120//! ```no_run
121//! # use atsamd_hal::{
122//! #     clock::v2::{
123//! #         clock_system_at_reset,
124//! #         gclk::{Gclk, GclkDiv8, GclkDiv16},
125//! #         pclk::Pclk,
126//! #     },
127//! #     gpio::Pins,
128//! #     pac::Peripherals,
129//! #     fugit::RateExtU32,
130//! # };
131//! # let mut pac = Peripherals::take().unwrap();
132//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
133//! #     pac.oscctrl,
134//! #     pac.osc32kctrl,
135//! #     pac.gclk,
136//! #     pac.mclk,
137//! #     &mut pac.nvmctrl,
138//! # );
139//! # let pins = Pins::new(pac.port);
140//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
141//! let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
142//! ```
143//!
144//! Note that the divider value supplied to `Gclk::div` must be wrapped by the
145//! [`GclkDiv16`] enum. This is for a few different reasons. First, [`Gclk1`]
146//! accepts a wider range of divider values than the other [`Gclk`]s, which use
147//! [`GclkDiv8`] instead. Second, the actual divider value is controlled by two
148//! register fields, and the set of valid values is best expressed as a Rust
149//! enum. The `GclkDiv8` and `GclkDiv16` enums are connected by the
150//! [`GclkDivider`] trait.
151//!
152//! Once [`Gclk1`] is enabled, we can use it to enable the [`Pclk`] for
153//! [`Sercom0`]. This follows the usual pattern. We provide a [`PclkToken`] and
154//! the [`EnabledGclk1`]. In return, we get an enabled [`Pclk`] and the
155//! [`EnabledGclk1`] counter is [`Increment`]ed.
156//!
157//! ```no_run
158//! # use atsamd_hal::{
159//! #     clock::v2::{
160//! #         clock_system_at_reset,
161//! #         gclk::{Gclk, GclkDiv8, GclkDiv16},
162//! #         pclk::Pclk,
163//! #     },
164//! #     gpio::Pins,
165//! #     pac::Peripherals,
166//! #     fugit::RateExtU32,
167//! # };
168//! # let mut pac = Peripherals::take().unwrap();
169//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
170//! #     pac.oscctrl,
171//! #     pac.osc32kctrl,
172//! #     pac.gclk,
173//! #     pac.mclk,
174//! #     &mut pac.nvmctrl,
175//! # );
176//! # let pins = Pins::new(pac.port);
177//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
178//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
179//! let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
180//! ```
181//!
182//! Next, we use [`Gclk1`] as a clock [`Source`] to create an instance of
183//! [`Gclk2`] with [`Gclk::from_source`]. However, keep in mind that this is
184//! only true for [`Gclk1`]. No other [`Gclk`] can act as a [`Source`] for
185//! another [`Gclk`].
186//!
187//! ```no_run
188//! # use atsamd_hal::{
189//! #     clock::v2::{
190//! #         clock_system_at_reset,
191//! #         gclk::{Gclk, GclkDiv8, GclkDiv16},
192//! #         pclk::Pclk,
193//! #     },
194//! #     gpio::Pins,
195//! #     pac::Peripherals,
196//! #     fugit::RateExtU32,
197//! # };
198//! # let mut pac = Peripherals::take().unwrap();
199//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
200//! #     pac.oscctrl,
201//! #     pac.osc32kctrl,
202//! #     pac.gclk,
203//! #     pac.mclk,
204//! #     &mut pac.nvmctrl,
205//! # );
206//! # let pins = Pins::new(pac.port);
207//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
208//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
209//! # let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
210//! let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
211//! ```
212//!
213//! The pattern repeats now. We divide [`Gclk1`] by 4 to produce the [`Gclk2`]
214//! output. Then we enable it to produce an [`EnabledGclk2`] and use it to yield
215//! another [`Pclk`].
216//!
217//! ```no_run
218//! # use atsamd_hal::{
219//! #     clock::v2::{
220//! #         clock_system_at_reset,
221//! #         gclk::{Gclk, GclkDiv8, GclkDiv16},
222//! #         pclk::Pclk,
223//! #     },
224//! #     gpio::Pins,
225//! #     pac::Peripherals,
226//! #     fugit::RateExtU32,
227//! # };
228//! # let mut pac = Peripherals::take().unwrap();
229//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
230//! #     pac.oscctrl,
231//! #     pac.osc32kctrl,
232//! #     pac.gclk,
233//! #     pac.mclk,
234//! #     &mut pac.nvmctrl,
235//! # );
236//! # let pins = Pins::new(pac.port);
237//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
238//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
239//! # let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
240//! # let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
241//! let gclk2 = gclk2.div(GclkDiv8::Div(4)).enable();
242//! let (pclk_sercom1, gclk2) = Pclk::enable(tokens.pclks.sercom1, gclk2);
243//! ```
244//!
245//! Finally, we output [`Gclk2`] directly to a GPIO pin. We supply the GPIO
246//! [`Pin`] to the [`EnabledGclk2`] to yield a [`GclkOut`].
247//!
248//! ```no_run
249//! # use atsamd_hal::{
250//! #     clock::v2::{
251//! #         clock_system_at_reset,
252//! #         gclk::{Gclk, GclkDiv8, GclkDiv16},
253//! #         pclk::Pclk,
254//! #     },
255//! #     gpio::Pins,
256//! #     pac::Peripherals,
257//! #     fugit::RateExtU32,
258//! # };
259//! # let mut pac = Peripherals::take().unwrap();
260//! # let (mut buses, clocks, tokens) = clock_system_at_reset(
261//! #     pac.oscctrl,
262//! #     pac.osc32kctrl,
263//! #     pac.gclk,
264//! #     pac.mclk,
265//! #     &mut pac.nvmctrl,
266//! # );
267//! # let pins = Pins::new(pac.port);
268//! # let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
269//! # let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
270//! # let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
271//! # let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
272//! # let gclk2 = gclk2.div(GclkDiv8::Div(4)).enable();
273//! # let (pclk_sercom1, gclk2) = Pclk::enable(tokens.pclks.sercom1, gclk2);
274//! let (gclk2, gclk2_out) = gclk2.enable_gclk_out(pins.pa16);
275//! ```
276//!
277//! The full example is provided below.
278//!
279//! ```no_run
280//! use atsamd_hal::{
281//!     clock::v2::{
282//!         clock_system_at_reset,
283//!         gclk::{Gclk, GclkDiv8, GclkDiv16},
284//!         pclk::Pclk,
285//!     },
286//!     gpio::Pins,
287//!     pac::Peripherals,
288//!     fugit::RateExtU32,
289//! };
290//! let mut pac = Peripherals::take().unwrap();
291//! let (mut buses, clocks, tokens) = clock_system_at_reset(
292//!     pac.oscctrl,
293//!     pac.osc32kctrl,
294//!     pac.gclk,
295//!     pac.mclk,
296//!     &mut pac.nvmctrl,
297//! );
298//! let pins = Pins::new(pac.port);
299//! let gclk1 = Gclk::from_pin(tokens.gclks.gclk1, pins.pb15, 24.MHz());
300//! let gclk1 = gclk1.div(GclkDiv16::Div(2)).enable();
301//! let (pclk_sercom0, gclk1) = Pclk::enable(tokens.pclks.sercom0, gclk1);
302//! let (gclk2, gclk1) = Gclk::from_source(tokens.gclks.gclk2, gclk1);
303//! let gclk2 = gclk2.div(GclkDiv8::Div(4)).enable();
304//! let (pclk_sercom1, gclk2) = Pclk::enable(tokens.pclks.sercom1, gclk2);
305//! let (gclk2, gclk2_out) = gclk2.enable_gclk_out(pins.pa16);
306//! ```
307//!
308//! ## `Gclk0`
309//!
310//! [`Gclk0`] is significant and special relative to the other [`Gclk`]s. It is
311//! the clock generator for the processor's main clock, so it can never be
312//! disabled. Consequently, it has a special API not available to the other
313//! `Gclk`s. While normal `Gclk`s can only change their clock [`Source`] or
314//! divider while disabled, `Gclk0` can never be disabled, so we provide this
315//! functionality on [`EnabledGclk0`] instead.
316//!
317//! We model the main clock's consumption of `Gclk0` by setting its [`Enabled`]
318//! counter to [`U1`] in [`clock_system_at_reset`]. This prevents users from
319//! ever disabling `EnabledGclk0`, because there is no way to [`Decrement`] its
320//! `Counter` to [`U0`].
321//!
322//! Additionally, we provide functions to change the clock `Source`, divider,
323//! etc. on `EnabledGclk0`, but we restrict them to the case where `N = U1`.
324//! This prevents users from changing its `Source` or divider if any *other,
325//! additional* clock consumes it (besides the main clock).
326//!
327//! [`clock_system_at_reset`]: super::clock_system_at_reset
328//! [`Xosc`]: super::xosc::Xosc
329//! [`Xosc32k`]: super::xosc32k::Xosc32k
330//! [`OscUlp32k`]: super::osculp32k::OscUlp32k
331//! [`Dfll`]: super::dfll::Dfll
332//! [`Dpll`]: super::dpll::Dpll
333//! [`PclkToken`]: super::pclk::PclkToken
334//! [`Pclk`]: super::pclk::Pclk
335//! [`Pins`]: crate::gpio::Pins
336//! [`Sercom0`]: crate::sercom::Sercom0
337
338use core::cmp::max;
339use core::marker::PhantomData;
340
341use paste::paste;
342use seq_macro::seq;
343use typenum::{U0, U1};
344
345use crate::pac;
346use crate::pac::gclk::genctrl::Divselselect;
347use crate::pac::Nvmctrl;
348
349use crate::gpio::{self, AlternateM, AnyPin, Pin, PinId};
350use crate::pac::gclk::genctrl::Srcselect;
351use crate::pac::gclk::Genctrl;
352use crate::time::Hertz;
353use crate::typelevel::{Decrement, Increment, PrivateDecrement, PrivateIncrement, Sealed};
354
355use super::dfll::DfllId;
356use super::dpll::{Dpll0Id, Dpll1Id};
357use super::osculp32k::OscUlp32kId;
358use super::xosc::{Xosc0Id, Xosc1Id};
359use super::xosc32k::Xosc32kId;
360use super::{Enabled, Source};
361
362//==============================================================================
363// GclkToken
364//==============================================================================
365
366/// Singleton token that can be exchanged for a [`Gclk`]
367///
368/// As explained in the [`clock` module documentation](super), instances of
369/// various `Token` types can be exchanged for actual clock types. They
370/// typically represent clocks that are disabled at power-on reset.
371///
372/// [`GclkToken`]s are no different. All [`Gclk`]s other than [`Gclk0`] are
373/// disabled at power-on reset. To use a [`Gclk`], you must first exchange the
374/// token for an actual clock with [`Gclk::from_source`] or [`Gclk::from_pin`].
375///
376/// [`GclkToken`] is generic over the [`GclkId`], where each corresponding token
377/// represents one of the 12 respective [`Gclk`]s.
378pub struct GclkToken<G: GclkId> {
379    gen: PhantomData<G>,
380}
381
382impl<G: GclkId> GclkToken<G> {
383    /// Create a new instance of [`GclkToken`]
384    ///
385    /// # Safety
386    ///
387    /// Each `GclkToken`s is a singleton. There must never be two simulatenous
388    /// instances with the same [`GclkId`]. See the notes on `Token` types and
389    /// memory safety in the root of the `clock` module for more details.
390    #[inline]
391    pub(super) unsafe fn new() -> Self {
392        GclkToken { gen: PhantomData }
393    }
394
395    /// SYNCBUSY register mask for the corresponding GCLK
396    const MASK: u16 = 1 << G::NUM;
397
398    /// Provide a reference to the corresponding [`Genctrl`] register
399    #[inline]
400    fn genctrl(&self) -> &Genctrl {
401        // Safety: Each `GclkToken` only has access to a mutually exclusive set
402        // of registers for the corresponding `GclkId`, and we use a shared
403        // reference to the register block. See the notes on `Token` types and
404        // memory safety in the root of the `clock` module for more details.
405        unsafe { (*pac::Gclk::PTR).genctrl(G::NUM) }
406    }
407
408    /// Block until synchronization has completed
409    ///
410    /// Reads or writes to synchronized fields must be accompanied by a check of
411    /// the `SYNCBUSY` register. See the datasheet for more details.
412    #[inline]
413    fn wait_syncbusy(&self) {
414        // Safety: We are only reading from the `SYNCBUSY` register, and we are
415        // only observing the bit corresponding to this particular `GclkId`, so
416        // there is no risk of memory corruption.
417        let syncbusy = unsafe { &(*pac::Gclk::PTR).syncbusy() };
418        while syncbusy.read().genctrl().bits() & Self::MASK != 0 {}
419    }
420
421    /// Set the clock source for this [`Gclk`]
422    #[inline]
423    fn set_source(&mut self, source: DynGclkSourceId) {
424        self.genctrl().modify(|_, w| w.src().variant(source.into()));
425        self.wait_syncbusy();
426    }
427
428    /// Set the [`GclkDivider`] value
429    ///
430    /// Use the internal interface of [`GclkDivider`] to set the `DIV` and
431    /// `DIVSEL` fields of the `GENCTRL` register.
432    #[inline]
433    fn set_div(&mut self, div: G::Divider) {
434        let (divsel, div) = div.divsel_div();
435        // Safety: The `DIVSEL` and `DIV` values are derived from the
436        // `GclkDivider` type, so they are guaranteed to be valid.
437        self.genctrl().modify(|_, w| unsafe {
438            w.divsel().variant(divsel);
439            w.div().bits(div)
440        });
441        self.wait_syncbusy();
442    }
443
444    /// Output a 50-50 duty-cycle clock when using an odd division factor
445    #[inline]
446    fn improve_duty_cycle(&mut self, flag: bool) {
447        self.genctrl().modify(|_, w| w.idc().bit(flag));
448        self.wait_syncbusy();
449    }
450
451    /// Set the state of [`GclkOut`] pins when the GCLK_IO output is disabled
452    #[inline]
453    fn output_off_value(&mut self, high: bool) {
454        self.genctrl().modify(|_, w| w.oov().bit(high));
455        self.wait_syncbusy();
456    }
457
458    /// Enable [`Gclk`] output to a GPIO [`Pin`]
459    #[inline]
460    fn enable_gclk_out(&mut self) {
461        self.genctrl().modify(|_, w| w.oe().set_bit());
462        self.wait_syncbusy();
463    }
464
465    /// Disable [`Gclk`] output on a GPIO [`Pin`]
466    ///
467    /// If a corresponding [`Pin`] is in the [`AlternateM`] mode, it's logic
468    /// level will depend on the [`output_off_value`].
469    #[inline]
470    fn disable_gclk_out(&mut self) {
471        self.genctrl().modify(|_, w| w.oe().clear_bit());
472        self.wait_syncbusy();
473    }
474
475    #[inline]
476    fn configure(&mut self, id: DynGclkSourceId, settings: Settings<G>) {
477        let (divsel, div) = settings.div.divsel_div();
478        self.genctrl().modify(|_, w| {
479            // Safety: The `DIVSEL` and `DIV` values are derived from the
480            // `GclkDivider` type, so they are guaranteed to be valid.
481            unsafe {
482                w.divsel().variant(divsel);
483                w.div().bits(div);
484            };
485            w.src().variant(id.into());
486            w.idc().bit(settings.improve_duty_cycle);
487            w.oov().bit(settings.output_off_value)
488        });
489        self.wait_syncbusy();
490    }
491
492    /// Enable the [`Gclk`]
493    #[inline]
494    fn enable(&mut self) {
495        self.genctrl().modify(|_, w| w.genen().set_bit());
496        self.wait_syncbusy();
497    }
498
499    /// Disable the [`Gclk`]
500    #[inline]
501    fn disable(&mut self) {
502        self.genctrl().modify(|_, w| w.genen().clear_bit());
503        self.wait_syncbusy();
504    }
505}
506
507//==============================================================================
508// DynGclkId
509//==============================================================================
510
511/// Value-level enum identifying one of 12 possible [`Gclk`]s
512///
513/// The variants of this enum identify one of the 12 possible generic clock
514/// generators.
515///
516/// `DynGclkId` is the value-level equivalent of [`GclkId`].
517pub enum DynGclkId {
518    Gclk0,
519    Gclk1,
520    Gclk2,
521    Gclk3,
522    Gclk4,
523    Gclk5,
524    Gclk6,
525    Gclk7,
526    Gclk8,
527    Gclk9,
528    Gclk10,
529    Gclk11,
530}
531
532//==============================================================================
533// GclkId
534//==============================================================================
535
536/// Type-level enum identifying one of 12 possible [`Gclk`]s
537///
538/// The types implementing this trait, i.e. [`Gclk0Id`] - [`Gclk11Id`], are
539/// type-level variants of `GclkId`, and they identify one of the 12 possible
540/// generic clock generators.
541///
542/// `GclkId` is the type-level equivalent of [`DynGclkId`]. See the
543/// documentation on [type-level programming] and specifically
544/// [type-level enums] for more details.
545///
546/// [type-level programming]: crate::typelevel
547/// [type-level enums]: crate::typelevel#type-level-enums
548pub trait GclkId: Sealed {
549    /// Corresponding variant of [`DynGclkId`]
550    const DYN: DynGclkId;
551    /// Corresponding numeric index (0..12)
552    const NUM: usize;
553    /// Corresponding [`GclkDivider`] type
554    ///
555    /// [`Gclk1`] uses [`GclkDiv16`], while all other [`Gclk`]s use
556    /// [`GclkDiv8`].
557    type Divider: GclkDivider;
558}
559
560/// Type-level variant of [`GclkId`] representing the identity of GCLK0
561///
562/// See the documentation on [type-level programming] and specifically
563/// [type-level enums] for more details.
564///
565/// [type-level programming]: crate::typelevel
566/// [type-level enums]: crate::typelevel#type-level-enums
567pub enum Gclk0Id {}
568impl Sealed for Gclk0Id {}
569impl GclkId for Gclk0Id {
570    const DYN: DynGclkId = DynGclkId::Gclk0;
571    const NUM: usize = 0;
572    type Divider = GclkDiv8;
573}
574
575/// Type-level variant of [`GclkId`] representing the identity of GCLK1
576///
577/// See the documentation on [type-level programming] and specifically
578/// [type-level enums] for more details.
579///
580/// [type-level programming]: crate::typelevel
581/// [type-level enums]: crate::typelevel#type-level-enums
582pub enum Gclk1Id {}
583impl Sealed for Gclk1Id {}
584impl GclkId for Gclk1Id {
585    const DYN: DynGclkId = DynGclkId::Gclk1;
586    const NUM: usize = 1;
587    type Divider = GclkDiv16;
588}
589
590seq!(N in 2..=11 {
591    paste! {
592        /// Type-level variant of [`GclkId`] representing the identity of
593        #[doc = "GCLK" N]
594        ///
595        /// See the documentation on [type-level programming] and specifically
596        /// [type-level enums] for more details.
597        ///
598        /// [type-level programming]: crate::typelevel
599        /// [type-level enums]: crate::typelevel#type-level-enums
600        pub enum [<Gclk N Id>] {}
601        impl Sealed for [<Gclk N Id>] {}
602        impl GclkId for [<Gclk N Id>] {
603            const DYN: DynGclkId = DynGclkId::Gclk~N;
604            const NUM: usize = N;
605            type Divider = GclkDiv8;
606        }
607    }
608});
609
610//==============================================================================
611// GclkDivider
612//==============================================================================
613
614/// Trait unifying the two [`Gclk`] divider types, [`GclkDiv8`] and
615/// [`GclkDiv16`]
616///
617/// Choosing a [`Gclk`] division factor can be complicated. [`Gclk1`] can accept
618/// a 16-bit divider value, while all other [`Gclk`]s only take an 8-bit value.
619/// Moreover, the set of valid clock dividers does not form a contiguous range.
620/// For example, the valid set of dividers for most [`Gclk`]s is 1-256 and 512.
621///
622/// The [`GclkDiv8`] and [`GclkDiv16`] enums provide simple and intuitive
623/// user-facing interfaces to choose the *actual* clock divider value. This
624/// trait, on the other hand, provides an internal-facing interface used by HAL
625/// authors to extract the clock divider and convert it to the corresponding
626/// `DIVSEL` and `DIV` register fields. Users should have no reason to interact
627/// with this trait directly.
628pub trait GclkDivider: Sealed + Default + Copy {
629    /// Returns the actual clock divider value as a `u32`
630    fn divider(&self) -> u32;
631    /// Return the corresponding `DIVSEL` and and `DIV` register fields
632    fn divsel_div(&self) -> (Divselselect, u16);
633}
634
635//==============================================================================
636// GclkDiv8
637//==============================================================================
638
639/// Enum for the clock division factor of all [`Gclk`]s other than [`Gclk1`]
640///
641/// Choosing a [`Gclk`] division factor can be complicated, because the set of
642/// valid values is not contiguous. For clocks other than [`Gclk1`], the
643/// division factor can be 1-256 or 512. `GclkDiv8` provides an enum interface
644/// to enforce validity of the division factor. See the datasheet for more
645/// details.
646#[derive(Clone, Copy)]
647pub enum GclkDiv8 {
648    /// Use a literal division factor
649    ///
650    /// All values in the range `[1-255]` are valid. Zero is also valid, but it
651    /// is interpreted as `1`.
652    Div(u8),
653    /// Use a division factor of `2^8 = 256`
654    Div2Pow8,
655    /// Use a division factor of `2^9 = 512`
656    Div2Pow9,
657}
658
659impl Sealed for GclkDiv8 {}
660
661impl Default for GclkDiv8 {
662    #[inline]
663    fn default() -> Self {
664        Self::Div(0)
665    }
666}
667
668impl GclkDivider for GclkDiv8 {
669    #[inline]
670    fn divider(&self) -> u32 {
671        match self {
672            GclkDiv8::Div(div) => (*div).into(),
673            GclkDiv8::Div2Pow8 => 256,
674            GclkDiv8::Div2Pow9 => 512,
675        }
676    }
677
678    #[inline]
679    fn divsel_div(&self) -> (Divselselect, u16) {
680        match self {
681            GclkDiv8::Div(div) => (Divselselect::Div1, (*div).into()),
682            GclkDiv8::Div2Pow8 => (Divselselect::Div2, 7),
683            GclkDiv8::Div2Pow9 => (Divselselect::Div2, 8),
684        }
685    }
686}
687
688//==============================================================================
689// GclkDiv16
690//==============================================================================
691
692/// Enum for the clock division factor of [`Gclk1`] only
693///
694/// Choosing the [`Gclk1`] division factor can be complicated, because the set
695/// of valid values is not contiguous. For [`Gclk1`], the division factor can be
696/// 1-65536 or 131072. `GclkDiv16` provides an enum interface to enforce
697/// validity of the division factor. See the datasheet for more details.
698#[derive(Clone, Copy)]
699pub enum GclkDiv16 {
700    /// Use a literal division factor
701    ///
702    /// All values in the range `[1-65535]` are valid. Zero is also valid, but
703    /// it is interpreted as `1`.
704    Div(u16),
705    /// Use a division factor of `2^16 = 65536`
706    Div2Pow16,
707    /// Use a division factor of `2^17 = 131072`
708    Div2Pow17,
709}
710
711impl Sealed for GclkDiv16 {}
712
713impl Default for GclkDiv16 {
714    #[inline]
715    fn default() -> Self {
716        Self::Div(0)
717    }
718}
719
720impl GclkDivider for GclkDiv16 {
721    #[inline]
722    fn divider(&self) -> u32 {
723        match self {
724            GclkDiv16::Div(div) => (*div).into(),
725            GclkDiv16::Div2Pow16 => 65536,
726            GclkDiv16::Div2Pow17 => 131072,
727        }
728    }
729
730    #[inline]
731    fn divsel_div(&self) -> (Divselselect, u16) {
732        match self {
733            GclkDiv16::Div(div) => (Divselselect::Div1, *div),
734            GclkDiv16::Div2Pow16 => (Divselselect::Div2, 15),
735            GclkDiv16::Div2Pow17 => (Divselselect::Div2, 16),
736        }
737    }
738}
739
740//==============================================================================
741// GclkIo
742//==============================================================================
743
744/// Trait mapping each [`PinId`] to its corresponding [`GclkId`] when used as a
745/// [`Gclk`] input or output
746///
747/// If a given [`PinId`] can be used as a [`Gclk`] input or output, it can only
748/// be used with one specific [`GclkId`]. This trait provides a mapping from
749/// such a `PinId` to its corresponding `GclkId`.
750pub trait GclkIo: PinId {
751    /// Corresponding [`GclkId`] for this [`PinId`]
752    type GclkId: GclkId;
753}
754
755// These implementations are much easier to read with `#[rustfmt::skip]`
756#[rustfmt::skip]
757mod gclkio_impl {
758    use atsamd_hal_macros::hal_cfg;
759
760    use super::*;
761
762    #[hal_cfg("pa10")]
763    impl GclkIo for gpio::PA10 { type GclkId = Gclk4Id; }
764    #[hal_cfg("pa11")]
765    impl GclkIo for gpio::PA11 { type GclkId = Gclk5Id; }
766    #[hal_cfg("pa14")]
767    impl GclkIo for gpio::PA14 { type GclkId = Gclk0Id; }
768    #[hal_cfg("pa15")]
769    impl GclkIo for gpio::PA15 { type GclkId = Gclk1Id; }
770    #[hal_cfg("pa16")]
771    impl GclkIo for gpio::PA16 { type GclkId = Gclk2Id; }
772    #[hal_cfg("pa17")]
773    impl GclkIo for gpio::PA17 { type GclkId = Gclk3Id; }
774    #[hal_cfg("pa27")]
775    impl GclkIo for gpio::PA27 { type GclkId = Gclk1Id; }
776    #[hal_cfg("pa30")]
777    impl GclkIo for gpio::PA30 { type GclkId = Gclk0Id; }
778    #[hal_cfg("pb10")]
779    impl GclkIo for gpio::PB10 { type GclkId = Gclk4Id; }
780    #[hal_cfg("pb11")]
781    impl GclkIo for gpio::PB11 { type GclkId = Gclk5Id; }
782    #[hal_cfg("pb12")]
783    impl GclkIo for gpio::PB12 { type GclkId = Gclk6Id; }
784    #[hal_cfg("pb13")]
785    impl GclkIo for gpio::PB13 { type GclkId = Gclk7Id; }
786    #[hal_cfg("pb14")]
787    impl GclkIo for gpio::PB14 { type GclkId = Gclk0Id; }
788    #[hal_cfg("pb15")]
789    impl GclkIo for gpio::PB15 { type GclkId = Gclk1Id; }
790    #[hal_cfg("pb16")]
791    impl GclkIo for gpio::PB16 { type GclkId = Gclk2Id; }
792    #[hal_cfg("pb17")]
793    impl GclkIo for gpio::PB17 { type GclkId = Gclk3Id; }
794    #[hal_cfg("pb18")]
795    impl GclkIo for gpio::PB18 { type GclkId = Gclk4Id; }
796    #[hal_cfg("pb19")]
797    impl GclkIo for gpio::PB19 { type GclkId = Gclk5Id; }
798    #[hal_cfg("pb20")]
799    impl GclkIo for gpio::PB20 { type GclkId = Gclk6Id; }
800    #[hal_cfg("pb21")]
801    impl GclkIo for gpio::PB21 { type GclkId = Gclk7Id; }
802    #[hal_cfg("pb22")]
803    impl GclkIo for gpio::PB22 { type GclkId = Gclk0Id; }
804    #[hal_cfg("pb23")]
805    impl GclkIo for gpio::PB23 { type GclkId = Gclk1Id; }
806}
807
808//==============================================================================
809// Gclk0Io
810//==============================================================================
811
812/// Set of [`PinId`]s whose implementations of [`GclkIo`] map to [`Gclk0Id`]
813///
814/// This is effectively a trait alias for [`PinId`]s that implement [`GclkIo`]
815/// with a `GclkId` associated type of [`Gclk0Id`], i.e.
816/// `GclkIo<GclkId = Gclk0Id>`. The trait is useful to simply some function
817/// signatures and to help type inference in a few cases.
818pub trait Gclk0Io
819where
820    Self: Sized,
821    Self: GclkIo<GclkId = Gclk0Id>,
822    Self: GclkSourceId<Resource = Pin<Self, AlternateM>>,
823{
824}
825
826impl<I: GclkIo<GclkId = Gclk0Id>> Gclk0Io for I {}
827
828//==============================================================================
829// DynGclkSourceId
830//==============================================================================
831
832/// Value-level enum of possible clock sources for a [`Gclk`]
833///
834/// The variants of this enum identify one of nine possible clock sources for
835/// a given [`Gclk`].
836///
837/// `DynGclkSourceId` is the value-level equivalent of [`GclkSourceId`].
838#[derive(Copy, Clone, PartialEq, Eq)]
839pub enum DynGclkSourceId {
840    Dfll,
841    Dpll0,
842    Dpll1,
843    Gclk1,
844    GclkIn,
845    OscUlp32k,
846    Xosc0,
847    Xosc1,
848    Xosc32k,
849}
850
851impl From<DynGclkSourceId> for Srcselect {
852    fn from(source: DynGclkSourceId) -> Self {
853        use DynGclkSourceId::*;
854        match source {
855            Dfll => Self::Dfll,
856            Dpll0 => Self::Dpll0,
857            Dpll1 => Self::Dpll1,
858            Gclk1 => Self::Gclkgen1,
859            GclkIn => Self::Gclkin,
860            OscUlp32k => Self::Osculp32k,
861            Xosc0 => Self::Xosc0,
862            Xosc1 => Self::Xosc1,
863            Xosc32k => Self::Xosc32k,
864        }
865    }
866}
867
868//==============================================================================
869// GclkSourceId
870//==============================================================================
871
872/// Type-level enum of possible clock [`Source`]s for a [`Gclk`]
873///
874/// The types implementing this trait are type-level variants of `GclkSourceId`,
875/// and they identify one of nine possible clock [`Source`]s for a given
876/// [`Gclk`]. All implementers of this trait are `Id` types, which are described
877/// in more detail in the [`clock` module documentation](super).
878///
879/// `GclkSourceId` is the type-level equivalent of [`DynGclkSourceId`]. See the
880/// documentation on [type-level programming] and specifically
881/// [type-level enums] for more details.
882///
883/// [type-level programming]: crate::typelevel
884/// [type-level enums]: crate::typelevel#type-level-enums
885pub trait GclkSourceId {
886    /// Corresponding variant of [`DynGclkSourceId`]
887    const DYN: DynGclkSourceId;
888
889    /// Resource to store in the [`Gclk`]
890    ///
891    /// Maps to the corresponding [`Pin`] for [`GclkIo`] types. In all other
892    /// cases, there is nothing to store, so it is `()`.
893    #[doc(hidden)]
894    type Resource;
895}
896
897impl GclkSourceId for DfllId {
898    const DYN: DynGclkSourceId = DynGclkSourceId::Dfll;
899    type Resource = ();
900}
901impl GclkSourceId for Dpll0Id {
902    const DYN: DynGclkSourceId = DynGclkSourceId::Dpll0;
903    type Resource = ();
904}
905impl GclkSourceId for Dpll1Id {
906    const DYN: DynGclkSourceId = DynGclkSourceId::Dpll1;
907    type Resource = ();
908}
909impl GclkSourceId for Gclk1Id {
910    const DYN: DynGclkSourceId = DynGclkSourceId::Gclk1;
911    type Resource = ();
912}
913impl<I: GclkIo> GclkSourceId for I {
914    const DYN: DynGclkSourceId = DynGclkSourceId::GclkIn;
915    type Resource = Pin<I, AlternateM>;
916}
917impl GclkSourceId for OscUlp32kId {
918    const DYN: DynGclkSourceId = DynGclkSourceId::OscUlp32k;
919    type Resource = ();
920}
921impl GclkSourceId for Xosc0Id {
922    const DYN: DynGclkSourceId = DynGclkSourceId::Xosc0;
923    type Resource = ();
924}
925impl GclkSourceId for Xosc1Id {
926    const DYN: DynGclkSourceId = DynGclkSourceId::Xosc1;
927    type Resource = ();
928}
929impl GclkSourceId for Xosc32kId {
930    const DYN: DynGclkSourceId = DynGclkSourceId::Xosc32k;
931    type Resource = ();
932}
933
934//==============================================================================
935// NotGclkIo
936//==============================================================================
937
938/// Type-level enum of [`GclkSourceId`] types that are not a [`GclkIo`]
939///
940/// The datasheet notes that a [`Gclk`] can use a GPIO [`Pin`] as either input
941/// or output, but not both. Stated differently, you cannot create a [`GclkOut`]
942/// from a `Gclk` where the [`GclkSourceId`] is a [`PinId`].
943///
944/// This trait acts as a [type-level enum] narrowing [`GclkSourceId`] to exclude
945/// any types which implement [`GclkIo`].
946///
947/// [type-level enum]: crate::typelevel#type-level-enums
948pub trait NotGclkIo: GclkSourceId<Resource = ()> {}
949
950impl<I: GclkSourceId<Resource = ()>> NotGclkIo for I {}
951
952//==============================================================================
953// Settings
954//==============================================================================
955
956/// Collection of [`Gclk`] settings to configure on enable
957struct Settings<G: GclkId> {
958    div: G::Divider,
959    output_off_value: bool,
960    improve_duty_cycle: bool,
961}
962
963impl<G: GclkId> Clone for Settings<G> {
964    fn clone(&self) -> Self {
965        *self
966    }
967}
968
969impl<G: GclkId> Copy for Settings<G> {}
970
971impl<G: GclkId> Default for Settings<G> {
972    fn default() -> Self {
973        Settings {
974            div: G::Divider::default(),
975            output_off_value: false,
976            improve_duty_cycle: false,
977        }
978    }
979}
980
981//==============================================================================
982// Gclk
983//==============================================================================
984
985/// Generic clock generator used to distribute clocks to various peripherals
986///
987/// A generic clock generator acts as a branch in the clock tree. It can connect
988/// a root or branch clock to other branch or leaf clocks. In particular, all
989/// peripheral [`Pclk`]s must be derived from a `Gclk`.
990///
991/// The type parameter `G` is a [`GclkId`] that determines which of the 12
992/// generators this [`Gclk`] represents ([`Gclk0`] - [`Gclk11`]). The type
993/// parameter `I` represents the `Id` type for the clock [`Source`] driving this
994/// `Gclk`. It must be one of the valid [`GclkSourceId`]s. Alternatively, if the
995/// `Gclk` is driven by a [GPIO](gpio) [`Pin`], then `I` is a [`PinId`]
996/// implementing [`GclkIo`]. See the [`clock` module documentation](super) for
997/// more detail on `Id` types.
998///
999/// On its own, an instance of `Gclk` does not represent an enabled clock
1000/// generator. Instead, it must first be wrapped with [`Enabled`], which
1001/// implements compile-time safety of the clock tree.
1002///
1003/// Because the terminal call to [`enable`] consumes the `Gclk` and returns an
1004/// [`EnabledGclk`], the remaining API uses the builder pattern, where each
1005/// method takes and returns `self` by value, allowing them to be easily
1006/// chained.
1007///
1008/// See the [module-level documentation](self) for an example of creating,
1009/// configuring and using a `Gclk`.
1010///
1011/// [`Pclk`]: super::pclk::Pclk
1012/// [`enable`]: Gclk::enable
1013pub struct Gclk<G, I>
1014where
1015    G: GclkId,
1016    I: GclkSourceId,
1017{
1018    token: GclkToken<G>,
1019    resource: I::Resource,
1020    src_freq: Hertz,
1021    settings: Settings<G>,
1022}
1023
1024/// An [`Enabled`] [`Gclk`]
1025///
1026/// As described in the [`clock` module documentation](super), the [`Enabled`]
1027/// wrapper implements compile-time clock tree safety by tracking the number of
1028/// clocks consuming this [`Gclk`] and restricts access to the underlying
1029/// [`Gclk`] to prevent misuse.
1030///
1031/// As with [`Enabled`], the default value for `N` is `U0`; if left unspecified,
1032/// the counter is assumed to be zero.
1033pub type EnabledGclk<G, I, N = U0> = Enabled<Gclk<G, I>, N>;
1034
1035/// Type alias for the corresponding [`Gclk`]
1036///
1037/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1038/// because it provides the processor main clock. We represent this by
1039/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1040/// prevents it from ever being disabled. Accordingly, we also provide a few
1041/// special methods on [`EnabledGclk0`] to configure the `Gclk` while it is
1042/// actively running.
1043pub type Gclk0<I> = Gclk<Gclk0Id, I>;
1044
1045/// Type alias for the corresponding [`EnabledGclk`]
1046///
1047/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1048/// because it provides the processor main clock. We represent this by
1049/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1050/// prevents it from ever being disabled. Thus, the default value for `N` is
1051/// [`U1`] instead of [`U0`]. Accordingly, we also provide a few special methods
1052/// on [`EnabledGclk0`] to configure the `Gclk` while it is actively running.
1053pub type EnabledGclk0<I, N = U1> = EnabledGclk<Gclk0Id, I, N>;
1054
1055seq!(G in 1..=11 {
1056    paste! {
1057        /// Type alias for the corresponding [`Gclk`]
1058        pub type Gclk~G<I> = Gclk<[<Gclk G Id>], I>;
1059
1060        /// Type alias for the corresponding [`EnabledGclk`]
1061        pub type EnabledGclk~G<I, N = U0> = EnabledGclk<[<Gclk G Id>], I, N>;
1062    }
1063});
1064
1065impl<G, I> Gclk<G, I>
1066where
1067    G: GclkId,
1068    I: GclkIo<GclkId = G>,
1069{
1070    /// Create a new [`Gclk`] from a GPIO [`Pin`]
1071    ///
1072    /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1073    /// only serves to consume the [`Pin`] and create a struct to track the GCLK
1074    /// configuration.
1075    ///
1076    /// The configuration data is stored until the user calls [`enable`]. At
1077    /// that point, all of the registers are written according to the
1078    /// initialization procedures specified in the datasheet, and an
1079    /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1080    /// that point.
1081    ///
1082    /// [`enable`]: Gclk::enable
1083    pub fn from_pin<P>(token: GclkToken<G>, pin: P, freq: impl Into<Hertz>) -> Self
1084    where
1085        P: AnyPin<Id = I>,
1086    {
1087        Gclk {
1088            token,
1089            resource: pin.into().into_mode(),
1090            src_freq: freq.into(),
1091            settings: Settings::default(),
1092        }
1093    }
1094
1095    /// Consume the [`Gclk`] and free its corresponding resources
1096    ///
1097    /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and GPIO
1098    /// [`Pin`].
1099    pub fn free_pin(self) -> (GclkToken<G>, Pin<I, AlternateM>) {
1100        (self.token, self.resource)
1101    }
1102}
1103
1104impl<G, I> Gclk<G, I>
1105where
1106    G: GclkId,
1107    I: NotGclkIo,
1108{
1109    /// Create a new [`Gclk`] from a clock [`Source`]
1110    ///
1111    /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1112    /// only serves to [`Increment`] the [`Source`]'s [`Enabled`] counter
1113    /// and create a struct to track the GCLK configuration.
1114    ///
1115    /// The configuration data is stored until the user calls [`enable`]. At
1116    /// that point, all of the registers are written according to the
1117    /// initialization procedures specified in the datasheet, and an
1118    /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1119    /// that point.
1120    ///
1121    /// [`enable`]: Gclk::enable
1122    #[inline]
1123    pub fn from_source<S>(token: GclkToken<G>, source: S) -> (Gclk<G, I>, S::Inc)
1124    where
1125        S: Source<Id = I> + Increment,
1126    {
1127        let config = Gclk {
1128            token,
1129            resource: (),
1130            src_freq: source.freq(),
1131            settings: Settings::default(),
1132        };
1133        (config, source.inc())
1134    }
1135
1136    /// Consume the [`Gclk`] and free its corresponding resources
1137    ///
1138    /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and
1139    /// [`Decrement`]s the [`Source`]'s [`Enabled`] counter.
1140    #[inline]
1141    pub fn free_source<S>(self, source: S) -> (GclkToken<G>, S::Dec)
1142    where
1143        S: Source<Id = I> + Decrement,
1144    {
1145        (self.token, source.dec())
1146    }
1147}
1148
1149impl<G, I> Gclk<G, I>
1150where
1151    G: GclkId,
1152    I: GclkSourceId,
1153{
1154    /// Modify the source of an existing clock
1155    ///
1156    /// This is a helper function for swapping Gclk0 to different clock sources.
1157    fn change_source<N: GclkSourceId>(
1158        mut self,
1159        resource: N::Resource,
1160        freq: Hertz,
1161    ) -> (Gclk<G, N>, I::Resource) {
1162        self.token.set_source(N::DYN);
1163        let gclk = Gclk {
1164            token: self.token,
1165            resource,
1166            src_freq: freq,
1167            settings: self.settings,
1168        };
1169        (gclk, self.resource)
1170    }
1171
1172    /// Set the [`GclkDivider`] value
1173    ///
1174    /// Set the clock division factor from input to output. This takes either a
1175    /// [`GclkDiv8`] or [`GclkDiv16`] enum, restricting the possible division
1176    /// factors to only the valid ones for the given [`Gclk`]. See the
1177    /// [`GclkDivider`] trait for more details.
1178    #[inline]
1179    #[allow(clippy::should_implement_trait)]
1180    pub fn div(mut self, div: G::Divider) -> Self {
1181        self.settings.div = div;
1182        self
1183    }
1184
1185    /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1186    #[inline]
1187    pub fn improve_duty_cycle(mut self, flag: bool) -> Self {
1188        self.settings.improve_duty_cycle = flag;
1189        self
1190    }
1191
1192    /// Return the [`Gclk`] ouput frequency
1193    ///
1194    /// This is the input frequency divided by the [`GclkDivider`].
1195    #[inline]
1196    pub fn freq(&self) -> Hertz {
1197        let div = max(1, self.settings.div.divider());
1198        self.src_freq / div
1199    }
1200
1201    /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1202    ///
1203    /// The output off value (OOV) determines the logic level of a [GPIO](gpio)
1204    /// [`Pin`] (configured as a [`GclkIo`] output) when the [`Gclk`] is
1205    /// disabled **OR** the [`GclkOut`] is disabled.
1206    ///
1207    /// As mentioned in the [`Gclk`] documentation, configuration options are
1208    /// not usually applied until the call to [`Gclk::enable`]. However, because
1209    /// the OOV is relevant when the `Gclk` is *disabled*, we make an exception.
1210    /// When calling this function, the new OOV will take effect immediately.
1211    ///
1212    /// However, remember that the `Pin` is not controlled by the `Gclk` unless
1213    /// the `Pin` is configured in [`AlternateM`] mode. `Pin`s are automatically
1214    /// set to `AlternateM` mode when calling [`enable_gclk_out`], but by that
1215    /// point, the OOV is irrelevant. If you need the `Pin` to be set to its
1216    /// OOV, you must *manually* set it to `AlternateM` mode before constructing
1217    /// the `GclkOut`.
1218    ///
1219    /// [`enable_gclk_out`]: EnabledGclk::enable_gclk_out
1220    #[inline]
1221    pub fn output_off_value(mut self, high: bool) -> Self {
1222        self.settings.output_off_value = high;
1223        self.token.output_off_value(high);
1224        self
1225    }
1226
1227    /// Enable the [`Gclk`], so that it can be used as a clock [`Source`]
1228    ///
1229    /// As mentioned in the [`Gclk`] documentation, no hardware registers are
1230    /// actually modified until this call. Rather, the desired configuration is
1231    /// stored internally, and the [`Gclk`] is initialized and configured here
1232    /// according to the datasheet.
1233    ///
1234    /// The returned value is an [`EnabledGclk`] that can be used as a clock
1235    /// [`Source`] for other clocks.
1236    #[inline]
1237    pub fn enable(mut self) -> EnabledGclk<G, I> {
1238        self.token.configure(I::DYN, self.settings);
1239        self.token.enable();
1240        Enabled::new(self)
1241    }
1242}
1243
1244impl<G, I> EnabledGclk<G, I>
1245where
1246    G: GclkId,
1247    I: GclkSourceId,
1248{
1249    /// Disable the [`Gclk`]
1250    ///
1251    /// This method is only implemented for `N = U0`, which means the clock can
1252    /// only be disabled when no other clocks consume this [`Gclk`].
1253    #[inline]
1254    pub fn disable(mut self) -> Gclk<G, I> {
1255        self.0.token.disable();
1256        self.0
1257    }
1258}
1259
1260/// Special methods for an [`Enabled`] [`Gclk0`]
1261///
1262/// [`Gclk0`] is special, because it drives the processor's main clock, which
1263/// can never be disabled. As discussed in the [module-level documentation],
1264/// this fact is represented by permanently [`Increment`]ing the counter for
1265/// [`EnabledGclk0`]. Thus, the minimum value for `N` is `U1` and
1266/// [`EnabledGclk0`] can never be disabled.
1267///
1268/// These methods represent actions that can be taken when `N = U1`, i.e. the
1269/// [`Enabled`] counter is at its minimum value. This is the only time it's
1270/// safe to change the [`Gclk0`] [`Source`] or change its [`GclkDivider`] value.
1271///
1272/// [module-level documentation]: self
1273impl<I: GclkSourceId> EnabledGclk0<I, U1> {
1274    /// Swap [`Gclk0`] from one clock [`Source`] to another
1275    ///
1276    /// `Gclk0` will remain fully enabled during the swap.
1277    #[inline]
1278    pub fn swap_sources<O, N>(self, old: O, new: N) -> (EnabledGclk0<N::Id, U1>, O::Dec, N::Inc)
1279    where
1280        O: Source<Id = I> + Decrement,
1281        N: Source + Increment,
1282        N::Id: NotGclkIo,
1283    {
1284        let (gclk, _) = self.0.change_source((), new.freq());
1285        let enabled = Enabled::new(gclk);
1286        (enabled, old.dec(), new.inc())
1287    }
1288
1289    /// Swap [`Gclk0`] from one [`GclkIo`] [`Pin`] to another
1290    ///
1291    /// `Gclk0` will remain fully enabled during the swap.
1292    #[inline]
1293    pub fn swap_pins<P>(
1294        self,
1295        pin: P,
1296        freq: impl Into<Hertz>,
1297    ) -> (EnabledGclk0<P::Id, U1>, Pin<I, AlternateM>)
1298    where
1299        I: Gclk0Io,
1300        P: AnyPin,
1301        P::Id: Gclk0Io,
1302    {
1303        let pin = pin.into().into_mode();
1304        let (gclk, pin) = self.0.change_source(pin, freq.into());
1305        let enabled = Enabled::new(gclk);
1306        (enabled, pin)
1307    }
1308
1309    /// Swap [`Gclk0`] from a clock [`Source`] to a [`GclkIo`] [`Pin`]
1310    ///
1311    /// `Gclk0` will remain fully enabled during the swap.
1312    #[inline]
1313    pub fn swap_source_for_pin<S, P>(
1314        self,
1315        source: S,
1316        pin: P,
1317        freq: impl Into<Hertz>,
1318    ) -> (EnabledGclk0<P::Id, U1>, S::Dec)
1319    where
1320        S: Source<Id = I> + Decrement,
1321        P: AnyPin,
1322        P::Id: Gclk0Io,
1323    {
1324        let pin = pin.into().into_mode();
1325        let (gclk, _) = self.0.change_source(pin, freq.into());
1326        let enabled = Enabled::new(gclk);
1327        (enabled, source.dec())
1328    }
1329
1330    /// Swap [`Gclk0`] from a [`GclkIo`] [`Pin`] to a clock [`Source`]
1331    ///
1332    /// `Gclk0` will remain fully enabled during the swap.
1333    #[inline]
1334    #[allow(clippy::type_complexity)]
1335    pub fn swap_pin_for_source<S>(
1336        self,
1337        source: S,
1338    ) -> (EnabledGclk0<S::Id, U1>, Pin<I, AlternateM>, S::Inc)
1339    where
1340        I: Gclk0Io,
1341        S: Source + Increment,
1342        S::Id: NotGclkIo,
1343    {
1344        let (gclk, pin) = self.0.change_source((), source.freq());
1345        let enabled = Enabled::new(gclk);
1346        (enabled, pin, source.inc())
1347    }
1348
1349    /// Set the [`GclkDivider`] value for [`Gclk0`]
1350    ///
1351    /// See [`Gclk::div`] documentation for more details.
1352    #[inline]
1353    pub fn div(&mut self, div: GclkDiv8) {
1354        self.0.settings.div = div;
1355        self.0.token.set_div(div);
1356    }
1357
1358    /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1359    #[inline]
1360    pub fn improve_duty_cycle(&mut self, flag: bool) {
1361        self.0.settings.improve_duty_cycle = flag;
1362        self.0.token.improve_duty_cycle(flag);
1363    }
1364
1365    /// Return the [`Gclk0`] frequency
1366    ///
1367    /// See [`Gclk::freq`] documentation for more details.
1368    #[inline]
1369    pub fn freq(&self) -> Hertz {
1370        self.0.freq()
1371    }
1372
1373    /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1374    ///
1375    /// See [`Gclk::output_off_value`] documentation for more details.
1376    #[inline]
1377    pub fn output_off_value(&mut self, high: bool) {
1378        self.0.settings.output_off_value = high;
1379        self.0.token.output_off_value(high);
1380    }
1381}
1382
1383//==============================================================================
1384// Source
1385//==============================================================================
1386
1387impl<G, I, N> Source for EnabledGclk<G, I, N>
1388where
1389    G: GclkId,
1390    I: GclkSourceId,
1391{
1392    type Id = G;
1393
1394    #[inline]
1395    fn freq(&self) -> Hertz {
1396        self.0.freq()
1397    }
1398}
1399
1400//==============================================================================
1401// Tokens
1402//==============================================================================
1403
1404seq!(N in 1..=11 {
1405    paste! {
1406        /// Set of [`GclkToken`]s representing the disabled [`Gclk`]s at
1407        /// power-on reset
1408        pub struct GclkTokens {
1409            #(
1410                /// [`GclkToken`] for
1411                #[doc = "[`Gclk" N "`]"]
1412                pub gclk~N: GclkToken<[<Gclk N Id>]>,
1413            )*
1414        }
1415
1416        impl GclkTokens {
1417            /// Create the set of [`GclkToken`]s
1418            ///
1419            /// # Safety
1420            ///
1421            /// All of the invariants required by `GclkToken::new` must be
1422            /// upheld here as well.
1423            #[inline]
1424            pub(super) unsafe fn new(nvmctrl: &mut Nvmctrl) -> Self {
1425                // Use auto wait states
1426                nvmctrl.ctrla().modify(|_, w| w.autows().set_bit());
1427                GclkTokens {
1428                    #( gclk~N: GclkToken::new(), )*
1429                }
1430            }
1431        }
1432    }
1433});
1434
1435//==============================================================================
1436// GclkOut
1437//==============================================================================
1438
1439/// A GPIO [`Pin`] configured as a [`Gclk`] output
1440///
1441/// The existence of this struct serves as proof that the corresponding [`Gclk`]
1442/// is [`Enabled`] and that it has been output to [`PinId`] `I`.
1443///
1444/// See the [module-level documentation](self) for an example of creating a
1445/// [`GclkOut`] from an [`EnabledGclk`].
1446pub struct GclkOut<I: GclkIo> {
1447    pin: Pin<I, AlternateM>,
1448    freq: Hertz,
1449}
1450
1451impl<G, I> GclkOut<I>
1452where
1453    G: GclkId,
1454    I: GclkIo<GclkId = G>,
1455{
1456    /// Return the frequency of the corresponding [`Gclk`]
1457    #[inline]
1458    pub fn freq(&self) -> Hertz {
1459        self.freq
1460    }
1461}
1462
1463impl<G, S, N> EnabledGclk<G, S, N>
1464where
1465    G: GclkId,
1466    S: NotGclkIo,
1467{
1468    /// Create and enable a [`GclkOut`]
1469    ///
1470    /// Enabling [`GclkIo`] output will [`Increment`] the `EnabledGclk`
1471    /// counter, which will prevent it from being disabled while the
1472    /// `GclkOut` exists.
1473    ///
1474    /// Note that a given [`Gclk`] can only use [`GclkIo`] for input **or**
1475    /// output, but not both simultaneously. The [`NotGclkIo`] trait exists to
1476    /// enforce this requirement.
1477    ///
1478    /// Finally, when a [`GclkOut`] is disabled, but the [`Pin`] is still in
1479    /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1480    /// the [`Gclk::output_off_value`] documentation for more details.
1481    #[inline]
1482    pub fn enable_gclk_out<P>(mut self, pin: P) -> (EnabledGclk<G, S, N::Inc>, GclkOut<P::Id>)
1483    where
1484        N: Increment,
1485        P: AnyPin,
1486        P::Id: GclkIo<GclkId = G>,
1487    {
1488        let pin = pin.into().into_mode();
1489        let freq = self.freq();
1490        self.0.token.enable_gclk_out();
1491        let gclk_out = GclkOut { pin, freq };
1492        (self.inc(), gclk_out)
1493    }
1494
1495    /// Disable a [`GclkOut`] and free its [`Pin`]
1496    ///
1497    /// Disabling [`GclkIo`] output will [`Decrement`] the [`EnabledGclk`]
1498    /// counter. When a [`GclkOut`] is disabled, but the [`Pin`] is still in
1499    /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1500    /// the [`Gclk::output_off_value`] documentation for more details.
1501    #[inline]
1502    pub fn disable_gclk_out<I>(
1503        mut self,
1504        gclk_out: GclkOut<I>,
1505    ) -> (EnabledGclk<G, S, N::Dec>, Pin<I, AlternateM>)
1506    where
1507        N: Decrement,
1508        I: GclkIo<GclkId = G>,
1509    {
1510        self.0.token.disable_gclk_out();
1511        (self.dec(), gclk_out.pin)
1512    }
1513}