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::Nvmctrl;
347use crate::pac::gclk::genctrl::Divselselect;
348
349use crate::gpio::{self, AlternateM, AnyPin, Pin, PinId};
350use crate::pac::gclk::Genctrl;
351use crate::pac::gclk::genctrl::Srcselect;
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    generator: 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 {
393            generator: PhantomData,
394        }
395    }
396
397    /// SYNCBUSY register mask for the corresponding GCLK
398    const MASK: u16 = 1 << G::NUM;
399
400    /// Provide a reference to the corresponding [`Genctrl`] register
401    #[inline]
402    fn genctrl(&self) -> &Genctrl {
403        // Safety: Each `GclkToken` only has access to a mutually exclusive set
404        // of registers for the corresponding `GclkId`, and we use a shared
405        // reference to the register block. See the notes on `Token` types and
406        // memory safety in the root of the `clock` module for more details.
407        unsafe { (*pac::Gclk::PTR).genctrl(G::NUM) }
408    }
409
410    /// Block until synchronization has completed
411    ///
412    /// Reads or writes to synchronized fields must be accompanied by a check of
413    /// the `SYNCBUSY` register. See the datasheet for more details.
414    #[inline]
415    fn wait_syncbusy(&self) {
416        // Safety: We are only reading from the `SYNCBUSY` register, and we are
417        // only observing the bit corresponding to this particular `GclkId`, so
418        // there is no risk of memory corruption.
419        let syncbusy = unsafe { &(*pac::Gclk::PTR).syncbusy() };
420        while syncbusy.read().genctrl().bits() & Self::MASK != 0 {}
421    }
422
423    /// Set the clock source for this [`Gclk`]
424    #[inline]
425    fn set_source(&mut self, source: DynGclkSourceId) {
426        self.genctrl().modify(|_, w| w.src().variant(source.into()));
427        self.wait_syncbusy();
428    }
429
430    /// Set the [`GclkDivider`] value
431    ///
432    /// Use the internal interface of [`GclkDivider`] to set the `DIV` and
433    /// `DIVSEL` fields of the `GENCTRL` register.
434    #[inline]
435    fn set_div(&mut self, div: G::Divider) {
436        let (divsel, div) = div.divsel_div();
437        // Safety: The `DIVSEL` and `DIV` values are derived from the
438        // `GclkDivider` type, so they are guaranteed to be valid.
439        self.genctrl().modify(|_, w| unsafe {
440            w.divsel().variant(divsel);
441            w.div().bits(div)
442        });
443        self.wait_syncbusy();
444    }
445
446    /// Output a 50-50 duty-cycle clock when using an odd division factor
447    #[inline]
448    fn improve_duty_cycle(&mut self, flag: bool) {
449        self.genctrl().modify(|_, w| w.idc().bit(flag));
450        self.wait_syncbusy();
451    }
452
453    /// Set the state of [`GclkOut`] pins when the GCLK_IO output is disabled
454    #[inline]
455    fn output_off_value(&mut self, high: bool) {
456        self.genctrl().modify(|_, w| w.oov().bit(high));
457        self.wait_syncbusy();
458    }
459
460    /// Enable [`Gclk`] output to a GPIO [`Pin`]
461    #[inline]
462    fn enable_gclk_out(&mut self) {
463        self.genctrl().modify(|_, w| w.oe().set_bit());
464        self.wait_syncbusy();
465    }
466
467    /// Disable [`Gclk`] output on a GPIO [`Pin`]
468    ///
469    /// If a corresponding [`Pin`] is in the [`AlternateM`] mode, it's logic
470    /// level will depend on the [`output_off_value`].
471    #[inline]
472    fn disable_gclk_out(&mut self) {
473        self.genctrl().modify(|_, w| w.oe().clear_bit());
474        self.wait_syncbusy();
475    }
476
477    #[inline]
478    fn configure(&mut self, id: DynGclkSourceId, settings: Settings<G>) {
479        let (divsel, div) = settings.div.divsel_div();
480        self.genctrl().modify(|_, w| {
481            // Safety: The `DIVSEL` and `DIV` values are derived from the
482            // `GclkDivider` type, so they are guaranteed to be valid.
483            unsafe {
484                w.divsel().variant(divsel);
485                w.div().bits(div);
486            };
487            w.src().variant(id.into());
488            w.idc().bit(settings.improve_duty_cycle);
489            w.oov().bit(settings.output_off_value)
490        });
491        self.wait_syncbusy();
492    }
493
494    /// Enable the [`Gclk`]
495    #[inline]
496    fn enable(&mut self) {
497        self.genctrl().modify(|_, w| w.genen().set_bit());
498        self.wait_syncbusy();
499    }
500
501    /// Disable the [`Gclk`]
502    #[inline]
503    fn disable(&mut self) {
504        self.genctrl().modify(|_, w| w.genen().clear_bit());
505        self.wait_syncbusy();
506    }
507}
508
509//==============================================================================
510// DynGclkId
511//==============================================================================
512
513/// Value-level enum identifying one of 12 possible [`Gclk`]s
514///
515/// The variants of this enum identify one of the 12 possible generic clock
516/// generators.
517///
518/// `DynGclkId` is the value-level equivalent of [`GclkId`].
519pub enum DynGclkId {
520    Gclk0,
521    Gclk1,
522    Gclk2,
523    Gclk3,
524    Gclk4,
525    Gclk5,
526    Gclk6,
527    Gclk7,
528    Gclk8,
529    Gclk9,
530    Gclk10,
531    Gclk11,
532}
533
534//==============================================================================
535// GclkId
536//==============================================================================
537
538/// Type-level enum identifying one of 12 possible [`Gclk`]s
539///
540/// The types implementing this trait, i.e. [`Gclk0Id`] - [`Gclk11Id`], are
541/// type-level variants of `GclkId`, and they identify one of the 12 possible
542/// generic clock generators.
543///
544/// `GclkId` is the type-level equivalent of [`DynGclkId`]. See the
545/// documentation on [type-level programming] and specifically
546/// [type-level enums] for more details.
547///
548/// [type-level programming]: crate::typelevel
549/// [type-level enums]: crate::typelevel#type-level-enums
550pub trait GclkId: Sealed {
551    /// Corresponding variant of [`DynGclkId`]
552    const DYN: DynGclkId;
553    /// Corresponding numeric index (0..12)
554    const NUM: usize;
555    /// Corresponding [`GclkDivider`] type
556    ///
557    /// [`Gclk1`] uses [`GclkDiv16`], while all other [`Gclk`]s use
558    /// [`GclkDiv8`].
559    type Divider: GclkDivider;
560}
561
562/// Type-level variant of [`GclkId`] representing the identity of GCLK0
563///
564/// See the documentation on [type-level programming] and specifically
565/// [type-level enums] for more details.
566///
567/// [type-level programming]: crate::typelevel
568/// [type-level enums]: crate::typelevel#type-level-enums
569pub enum Gclk0Id {}
570impl Sealed for Gclk0Id {}
571impl GclkId for Gclk0Id {
572    const DYN: DynGclkId = DynGclkId::Gclk0;
573    const NUM: usize = 0;
574    type Divider = GclkDiv8;
575}
576
577/// Type-level variant of [`GclkId`] representing the identity of GCLK1
578///
579/// See the documentation on [type-level programming] and specifically
580/// [type-level enums] for more details.
581///
582/// [type-level programming]: crate::typelevel
583/// [type-level enums]: crate::typelevel#type-level-enums
584pub enum Gclk1Id {}
585impl Sealed for Gclk1Id {}
586impl GclkId for Gclk1Id {
587    const DYN: DynGclkId = DynGclkId::Gclk1;
588    const NUM: usize = 1;
589    type Divider = GclkDiv16;
590}
591
592seq!(N in 2..=11 {
593    paste! {
594        /// Type-level variant of [`GclkId`] representing the identity of
595        #[doc = "GCLK" N]
596        ///
597        /// See the documentation on [type-level programming] and specifically
598        /// [type-level enums] for more details.
599        ///
600        /// [type-level programming]: crate::typelevel
601        /// [type-level enums]: crate::typelevel#type-level-enums
602        pub enum [<Gclk N Id>] {}
603        impl Sealed for [<Gclk N Id>] {}
604        impl GclkId for [<Gclk N Id>] {
605            const DYN: DynGclkId = DynGclkId::Gclk~N;
606            const NUM: usize = N;
607            type Divider = GclkDiv8;
608        }
609    }
610});
611
612//==============================================================================
613// GclkDivider
614//==============================================================================
615
616/// Trait unifying the two [`Gclk`] divider types, [`GclkDiv8`] and
617/// [`GclkDiv16`]
618///
619/// Choosing a [`Gclk`] division factor can be complicated. [`Gclk1`] can accept
620/// a 16-bit divider value, while all other [`Gclk`]s only take an 8-bit value.
621/// Moreover, the set of valid clock dividers does not form a contiguous range.
622/// For example, the valid set of dividers for most [`Gclk`]s is 1-256 and 512.
623///
624/// The [`GclkDiv8`] and [`GclkDiv16`] enums provide simple and intuitive
625/// user-facing interfaces to choose the *actual* clock divider value. This
626/// trait, on the other hand, provides an internal-facing interface used by HAL
627/// authors to extract the clock divider and convert it to the corresponding
628/// `DIVSEL` and `DIV` register fields. Users should have no reason to interact
629/// with this trait directly.
630pub trait GclkDivider: Sealed + Default + Copy {
631    /// Returns the actual clock divider value as a `u32`
632    fn divider(&self) -> u32;
633    /// Return the corresponding `DIVSEL` and and `DIV` register fields
634    fn divsel_div(&self) -> (Divselselect, u16);
635}
636
637//==============================================================================
638// GclkDiv8
639//==============================================================================
640
641/// Enum for the clock division factor of all [`Gclk`]s other than [`Gclk1`]
642///
643/// Choosing a [`Gclk`] division factor can be complicated, because the set of
644/// valid values is not contiguous. For clocks other than [`Gclk1`], the
645/// division factor can be 1-256 or 512. `GclkDiv8` provides an enum interface
646/// to enforce validity of the division factor. See the datasheet for more
647/// details.
648#[derive(Clone, Copy)]
649pub enum GclkDiv8 {
650    /// Use a literal division factor
651    ///
652    /// All values in the range `[1-255]` are valid. Zero is also valid, but it
653    /// is interpreted as `1`.
654    Div(u8),
655    /// Use a division factor of `2^8 = 256`
656    Div2Pow8,
657    /// Use a division factor of `2^9 = 512`
658    Div2Pow9,
659}
660
661impl Sealed for GclkDiv8 {}
662
663impl Default for GclkDiv8 {
664    #[inline]
665    fn default() -> Self {
666        Self::Div(0)
667    }
668}
669
670impl GclkDivider for GclkDiv8 {
671    #[inline]
672    fn divider(&self) -> u32 {
673        match self {
674            GclkDiv8::Div(div) => (*div).into(),
675            GclkDiv8::Div2Pow8 => 256,
676            GclkDiv8::Div2Pow9 => 512,
677        }
678    }
679
680    #[inline]
681    fn divsel_div(&self) -> (Divselselect, u16) {
682        match self {
683            GclkDiv8::Div(div) => (Divselselect::Div1, (*div).into()),
684            GclkDiv8::Div2Pow8 => (Divselselect::Div2, 7),
685            GclkDiv8::Div2Pow9 => (Divselselect::Div2, 8),
686        }
687    }
688}
689
690//==============================================================================
691// GclkDiv16
692//==============================================================================
693
694/// Enum for the clock division factor of [`Gclk1`] only
695///
696/// Choosing the [`Gclk1`] division factor can be complicated, because the set
697/// of valid values is not contiguous. For [`Gclk1`], the division factor can be
698/// 1-65536 or 131072. `GclkDiv16` provides an enum interface to enforce
699/// validity of the division factor. See the datasheet for more details.
700#[derive(Clone, Copy)]
701pub enum GclkDiv16 {
702    /// Use a literal division factor
703    ///
704    /// All values in the range `[1-65535]` are valid. Zero is also valid, but
705    /// it is interpreted as `1`.
706    Div(u16),
707    /// Use a division factor of `2^16 = 65536`
708    Div2Pow16,
709    /// Use a division factor of `2^17 = 131072`
710    Div2Pow17,
711}
712
713impl Sealed for GclkDiv16 {}
714
715impl Default for GclkDiv16 {
716    #[inline]
717    fn default() -> Self {
718        Self::Div(0)
719    }
720}
721
722impl GclkDivider for GclkDiv16 {
723    #[inline]
724    fn divider(&self) -> u32 {
725        match self {
726            GclkDiv16::Div(div) => (*div).into(),
727            GclkDiv16::Div2Pow16 => 65536,
728            GclkDiv16::Div2Pow17 => 131072,
729        }
730    }
731
732    #[inline]
733    fn divsel_div(&self) -> (Divselselect, u16) {
734        match self {
735            GclkDiv16::Div(div) => (Divselselect::Div1, *div),
736            GclkDiv16::Div2Pow16 => (Divselselect::Div2, 15),
737            GclkDiv16::Div2Pow17 => (Divselselect::Div2, 16),
738        }
739    }
740}
741
742//==============================================================================
743// GclkIo
744//==============================================================================
745
746/// Trait mapping each [`PinId`] to its corresponding [`GclkId`] when used as a
747/// [`Gclk`] input or output
748///
749/// If a given [`PinId`] can be used as a [`Gclk`] input or output, it can only
750/// be used with one specific [`GclkId`]. This trait provides a mapping from
751/// such a `PinId` to its corresponding `GclkId`.
752pub trait GclkIo: PinId {
753    /// Corresponding [`GclkId`] for this [`PinId`]
754    type GclkId: GclkId;
755}
756
757// These implementations are much easier to read with `#[rustfmt::skip]`
758#[rustfmt::skip]
759mod gclkio_impl {
760    use atsamd_hal_macros::hal_cfg;
761
762    use super::*;
763
764    #[hal_cfg("pa10")]
765    impl GclkIo for gpio::PA10 { type GclkId = Gclk4Id; }
766    #[hal_cfg("pa11")]
767    impl GclkIo for gpio::PA11 { type GclkId = Gclk5Id; }
768    #[hal_cfg("pa14")]
769    impl GclkIo for gpio::PA14 { type GclkId = Gclk0Id; }
770    #[hal_cfg("pa15")]
771    impl GclkIo for gpio::PA15 { type GclkId = Gclk1Id; }
772    #[hal_cfg("pa16")]
773    impl GclkIo for gpio::PA16 { type GclkId = Gclk2Id; }
774    #[hal_cfg("pa17")]
775    impl GclkIo for gpio::PA17 { type GclkId = Gclk3Id; }
776    #[hal_cfg("pa27")]
777    impl GclkIo for gpio::PA27 { type GclkId = Gclk1Id; }
778    #[hal_cfg("pa30")]
779    impl GclkIo for gpio::PA30 { type GclkId = Gclk0Id; }
780    #[hal_cfg("pb10")]
781    impl GclkIo for gpio::PB10 { type GclkId = Gclk4Id; }
782    #[hal_cfg("pb11")]
783    impl GclkIo for gpio::PB11 { type GclkId = Gclk5Id; }
784    #[hal_cfg("pb12")]
785    impl GclkIo for gpio::PB12 { type GclkId = Gclk6Id; }
786    #[hal_cfg("pb13")]
787    impl GclkIo for gpio::PB13 { type GclkId = Gclk7Id; }
788    #[hal_cfg("pb14")]
789    impl GclkIo for gpio::PB14 { type GclkId = Gclk0Id; }
790    #[hal_cfg("pb15")]
791    impl GclkIo for gpio::PB15 { type GclkId = Gclk1Id; }
792    #[hal_cfg("pb16")]
793    impl GclkIo for gpio::PB16 { type GclkId = Gclk2Id; }
794    #[hal_cfg("pb17")]
795    impl GclkIo for gpio::PB17 { type GclkId = Gclk3Id; }
796    #[hal_cfg("pb18")]
797    impl GclkIo for gpio::PB18 { type GclkId = Gclk4Id; }
798    #[hal_cfg("pb19")]
799    impl GclkIo for gpio::PB19 { type GclkId = Gclk5Id; }
800    #[hal_cfg("pb20")]
801    impl GclkIo for gpio::PB20 { type GclkId = Gclk6Id; }
802    #[hal_cfg("pb21")]
803    impl GclkIo for gpio::PB21 { type GclkId = Gclk7Id; }
804    #[hal_cfg("pb22")]
805    impl GclkIo for gpio::PB22 { type GclkId = Gclk0Id; }
806    #[hal_cfg("pb23")]
807    impl GclkIo for gpio::PB23 { type GclkId = Gclk1Id; }
808}
809
810//==============================================================================
811// Gclk0Io
812//==============================================================================
813
814/// Set of [`PinId`]s whose implementations of [`GclkIo`] map to [`Gclk0Id`]
815///
816/// This is effectively a trait alias for [`PinId`]s that implement [`GclkIo`]
817/// with a `GclkId` associated type of [`Gclk0Id`], i.e.
818/// `GclkIo<GclkId = Gclk0Id>`. The trait is useful to simply some function
819/// signatures and to help type inference in a few cases.
820pub trait Gclk0Io
821where
822    Self: Sized,
823    Self: GclkIo<GclkId = Gclk0Id>,
824    Self: GclkSourceId<Resource = Pin<Self, AlternateM>>,
825{
826}
827
828impl<I: GclkIo<GclkId = Gclk0Id>> Gclk0Io for I {}
829
830//==============================================================================
831// DynGclkSourceId
832//==============================================================================
833
834/// Value-level enum of possible clock sources for a [`Gclk`]
835///
836/// The variants of this enum identify one of nine possible clock sources for
837/// a given [`Gclk`].
838///
839/// `DynGclkSourceId` is the value-level equivalent of [`GclkSourceId`].
840#[derive(Copy, Clone, PartialEq, Eq)]
841pub enum DynGclkSourceId {
842    Dfll,
843    Dpll0,
844    Dpll1,
845    Gclk1,
846    GclkIn,
847    OscUlp32k,
848    Xosc0,
849    Xosc1,
850    Xosc32k,
851}
852
853impl From<DynGclkSourceId> for Srcselect {
854    fn from(source: DynGclkSourceId) -> Self {
855        use DynGclkSourceId::*;
856        match source {
857            Dfll => Self::Dfll,
858            Dpll0 => Self::Dpll0,
859            Dpll1 => Self::Dpll1,
860            Gclk1 => Self::Gclkgen1,
861            GclkIn => Self::Gclkin,
862            OscUlp32k => Self::Osculp32k,
863            Xosc0 => Self::Xosc0,
864            Xosc1 => Self::Xosc1,
865            Xosc32k => Self::Xosc32k,
866        }
867    }
868}
869
870//==============================================================================
871// GclkSourceId
872//==============================================================================
873
874/// Type-level enum of possible clock [`Source`]s for a [`Gclk`]
875///
876/// The types implementing this trait are type-level variants of `GclkSourceId`,
877/// and they identify one of nine possible clock [`Source`]s for a given
878/// [`Gclk`]. All implementers of this trait are `Id` types, which are described
879/// in more detail in the [`clock` module documentation](super).
880///
881/// `GclkSourceId` is the type-level equivalent of [`DynGclkSourceId`]. See the
882/// documentation on [type-level programming] and specifically
883/// [type-level enums] for more details.
884///
885/// [type-level programming]: crate::typelevel
886/// [type-level enums]: crate::typelevel#type-level-enums
887pub trait GclkSourceId {
888    /// Corresponding variant of [`DynGclkSourceId`]
889    const DYN: DynGclkSourceId;
890
891    /// Resource to store in the [`Gclk`]
892    ///
893    /// Maps to the corresponding [`Pin`] for [`GclkIo`] types. In all other
894    /// cases, there is nothing to store, so it is `()`.
895    #[doc(hidden)]
896    type Resource;
897}
898
899impl GclkSourceId for DfllId {
900    const DYN: DynGclkSourceId = DynGclkSourceId::Dfll;
901    type Resource = ();
902}
903impl GclkSourceId for Dpll0Id {
904    const DYN: DynGclkSourceId = DynGclkSourceId::Dpll0;
905    type Resource = ();
906}
907impl GclkSourceId for Dpll1Id {
908    const DYN: DynGclkSourceId = DynGclkSourceId::Dpll1;
909    type Resource = ();
910}
911impl GclkSourceId for Gclk1Id {
912    const DYN: DynGclkSourceId = DynGclkSourceId::Gclk1;
913    type Resource = ();
914}
915impl<I: GclkIo> GclkSourceId for I {
916    const DYN: DynGclkSourceId = DynGclkSourceId::GclkIn;
917    type Resource = Pin<I, AlternateM>;
918}
919impl GclkSourceId for OscUlp32kId {
920    const DYN: DynGclkSourceId = DynGclkSourceId::OscUlp32k;
921    type Resource = ();
922}
923impl GclkSourceId for Xosc0Id {
924    const DYN: DynGclkSourceId = DynGclkSourceId::Xosc0;
925    type Resource = ();
926}
927impl GclkSourceId for Xosc1Id {
928    const DYN: DynGclkSourceId = DynGclkSourceId::Xosc1;
929    type Resource = ();
930}
931impl GclkSourceId for Xosc32kId {
932    const DYN: DynGclkSourceId = DynGclkSourceId::Xosc32k;
933    type Resource = ();
934}
935
936//==============================================================================
937// NotGclkIo
938//==============================================================================
939
940/// Type-level enum of [`GclkSourceId`] types that are not a [`GclkIo`]
941///
942/// The datasheet notes that a [`Gclk`] can use a GPIO [`Pin`] as either input
943/// or output, but not both. Stated differently, you cannot create a [`GclkOut`]
944/// from a `Gclk` where the [`GclkSourceId`] is a [`PinId`].
945///
946/// This trait acts as a [type-level enum] narrowing [`GclkSourceId`] to exclude
947/// any types which implement [`GclkIo`].
948///
949/// [type-level enum]: crate::typelevel#type-level-enums
950pub trait NotGclkIo: GclkSourceId<Resource = ()> {}
951
952impl<I: GclkSourceId<Resource = ()>> NotGclkIo for I {}
953
954//==============================================================================
955// Settings
956//==============================================================================
957
958/// Collection of [`Gclk`] settings to configure on enable
959struct Settings<G: GclkId> {
960    div: G::Divider,
961    output_off_value: bool,
962    improve_duty_cycle: bool,
963}
964
965impl<G: GclkId> Clone for Settings<G> {
966    fn clone(&self) -> Self {
967        *self
968    }
969}
970
971impl<G: GclkId> Copy for Settings<G> {}
972
973impl<G: GclkId> Default for Settings<G> {
974    fn default() -> Self {
975        Settings {
976            div: G::Divider::default(),
977            output_off_value: false,
978            improve_duty_cycle: false,
979        }
980    }
981}
982
983//==============================================================================
984// Gclk
985//==============================================================================
986
987/// Generic clock generator used to distribute clocks to various peripherals
988///
989/// A generic clock generator acts as a branch in the clock tree. It can connect
990/// a root or branch clock to other branch or leaf clocks. In particular, all
991/// peripheral [`Pclk`]s must be derived from a `Gclk`.
992///
993/// The type parameter `G` is a [`GclkId`] that determines which of the 12
994/// generators this [`Gclk`] represents ([`Gclk0`] - [`Gclk11`]). The type
995/// parameter `I` represents the `Id` type for the clock [`Source`] driving this
996/// `Gclk`. It must be one of the valid [`GclkSourceId`]s. Alternatively, if the
997/// `Gclk` is driven by a [GPIO](gpio) [`Pin`], then `I` is a [`PinId`]
998/// implementing [`GclkIo`]. See the [`clock` module documentation](super) for
999/// more detail on `Id` types.
1000///
1001/// On its own, an instance of `Gclk` does not represent an enabled clock
1002/// generator. Instead, it must first be wrapped with [`Enabled`], which
1003/// implements compile-time safety of the clock tree.
1004///
1005/// Because the terminal call to [`enable`] consumes the `Gclk` and returns an
1006/// [`EnabledGclk`], the remaining API uses the builder pattern, where each
1007/// method takes and returns `self` by value, allowing them to be easily
1008/// chained.
1009///
1010/// See the [module-level documentation](self) for an example of creating,
1011/// configuring and using a `Gclk`.
1012///
1013/// [`Pclk`]: super::pclk::Pclk
1014/// [`enable`]: Gclk::enable
1015pub struct Gclk<G, I>
1016where
1017    G: GclkId,
1018    I: GclkSourceId,
1019{
1020    token: GclkToken<G>,
1021    resource: I::Resource,
1022    src_freq: Hertz,
1023    settings: Settings<G>,
1024}
1025
1026/// An [`Enabled`] [`Gclk`]
1027///
1028/// As described in the [`clock` module documentation](super), the [`Enabled`]
1029/// wrapper implements compile-time clock tree safety by tracking the number of
1030/// clocks consuming this [`Gclk`] and restricts access to the underlying
1031/// [`Gclk`] to prevent misuse.
1032///
1033/// As with [`Enabled`], the default value for `N` is `U0`; if left unspecified,
1034/// the counter is assumed to be zero.
1035pub type EnabledGclk<G, I, N = U0> = Enabled<Gclk<G, I>, N>;
1036
1037/// Type alias for the corresponding [`Gclk`]
1038///
1039/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1040/// because it provides the processor main clock. We represent this by
1041/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1042/// prevents it from ever being disabled. Accordingly, we also provide a few
1043/// special methods on [`EnabledGclk0`] to configure the `Gclk` while it is
1044/// actively running.
1045pub type Gclk0<I> = Gclk<Gclk0Id, I>;
1046
1047/// Type alias for the corresponding [`EnabledGclk`]
1048///
1049/// As mentioned in the [module-level documentation](self), `Gclk0` is special,
1050/// because it provides the processor main clock. We represent this by
1051/// permanently [`Increment`]ing the counter for [`EnabledGclk0`], which
1052/// prevents it from ever being disabled. Thus, the default value for `N` is
1053/// [`U1`] instead of [`U0`]. Accordingly, we also provide a few special methods
1054/// on [`EnabledGclk0`] to configure the `Gclk` while it is actively running.
1055pub type EnabledGclk0<I, N = U1> = EnabledGclk<Gclk0Id, I, N>;
1056
1057seq!(G in 1..=11 {
1058    paste! {
1059        /// Type alias for the corresponding [`Gclk`]
1060        pub type Gclk~G<I> = Gclk<[<Gclk G Id>], I>;
1061
1062        /// Type alias for the corresponding [`EnabledGclk`]
1063        pub type EnabledGclk~G<I, N = U0> = EnabledGclk<[<Gclk G Id>], I, N>;
1064    }
1065});
1066
1067impl<G, I> Gclk<G, I>
1068where
1069    G: GclkId,
1070    I: GclkIo<GclkId = G>,
1071{
1072    /// Create a new [`Gclk`] from a GPIO [`Pin`]
1073    ///
1074    /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1075    /// only serves to consume the [`Pin`] and create a struct to track the GCLK
1076    /// configuration.
1077    ///
1078    /// The configuration data is stored until the user calls [`enable`]. At
1079    /// that point, all of the registers are written according to the
1080    /// initialization procedures specified in the datasheet, and an
1081    /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1082    /// that point.
1083    ///
1084    /// [`enable`]: Gclk::enable
1085    pub fn from_pin<P>(token: GclkToken<G>, pin: P, freq: impl Into<Hertz>) -> Self
1086    where
1087        P: AnyPin<Id = I>,
1088    {
1089        Gclk {
1090            token,
1091            resource: pin.into().into_mode(),
1092            src_freq: freq.into(),
1093            settings: Settings::default(),
1094        }
1095    }
1096
1097    /// Consume the [`Gclk`] and free its corresponding resources
1098    ///
1099    /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and GPIO
1100    /// [`Pin`].
1101    pub fn free_pin(self) -> (GclkToken<G>, Pin<I, AlternateM>) {
1102        (self.token, self.resource)
1103    }
1104}
1105
1106impl<G, I> Gclk<G, I>
1107where
1108    G: GclkId,
1109    I: NotGclkIo,
1110{
1111    /// Create a new [`Gclk`] from a clock [`Source`]
1112    ///
1113    /// Creating a [`Gclk`] does not modify any of the hardware registers. It
1114    /// only serves to [`Increment`] the [`Source`]'s [`Enabled`] counter
1115    /// and create a struct to track the GCLK configuration.
1116    ///
1117    /// The configuration data is stored until the user calls [`enable`]. At
1118    /// that point, all of the registers are written according to the
1119    /// initialization procedures specified in the datasheet, and an
1120    /// [`EnabledGclk`] is returned. The `Gclk` is not active or useful until
1121    /// that point.
1122    ///
1123    /// [`enable`]: Gclk::enable
1124    #[inline]
1125    pub fn from_source<S>(token: GclkToken<G>, source: S) -> (Gclk<G, I>, S::Inc)
1126    where
1127        S: Source<Id = I> + Increment,
1128    {
1129        let config = Gclk {
1130            token,
1131            resource: (),
1132            src_freq: source.freq(),
1133            settings: Settings::default(),
1134        };
1135        (config, source.inc())
1136    }
1137
1138    /// Consume the [`Gclk`] and free its corresponding resources
1139    ///
1140    /// Freeing a [`Gclk`] returns the corresponding [`GclkToken`] and
1141    /// [`Decrement`]s the [`Source`]'s [`Enabled`] counter.
1142    #[inline]
1143    pub fn free_source<S>(self, source: S) -> (GclkToken<G>, S::Dec)
1144    where
1145        S: Source<Id = I> + Decrement,
1146    {
1147        (self.token, source.dec())
1148    }
1149}
1150
1151impl<G, I> Gclk<G, I>
1152where
1153    G: GclkId,
1154    I: GclkSourceId,
1155{
1156    /// Modify the source of an existing clock
1157    ///
1158    /// This is a helper function for swapping Gclk0 to different clock sources.
1159    fn change_source<N: GclkSourceId>(
1160        mut self,
1161        resource: N::Resource,
1162        freq: Hertz,
1163    ) -> (Gclk<G, N>, I::Resource) {
1164        self.token.set_source(N::DYN);
1165        let gclk = Gclk {
1166            token: self.token,
1167            resource,
1168            src_freq: freq,
1169            settings: self.settings,
1170        };
1171        (gclk, self.resource)
1172    }
1173
1174    /// Set the [`GclkDivider`] value
1175    ///
1176    /// Set the clock division factor from input to output. This takes either a
1177    /// [`GclkDiv8`] or [`GclkDiv16`] enum, restricting the possible division
1178    /// factors to only the valid ones for the given [`Gclk`]. See the
1179    /// [`GclkDivider`] trait for more details.
1180    #[inline]
1181    #[allow(clippy::should_implement_trait)]
1182    pub fn div(mut self, div: G::Divider) -> Self {
1183        self.settings.div = div;
1184        self
1185    }
1186
1187    /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1188    #[inline]
1189    pub fn improve_duty_cycle(mut self, flag: bool) -> Self {
1190        self.settings.improve_duty_cycle = flag;
1191        self
1192    }
1193
1194    /// Return the [`Gclk`] ouput frequency
1195    ///
1196    /// This is the input frequency divided by the [`GclkDivider`].
1197    #[inline]
1198    pub fn freq(&self) -> Hertz {
1199        let div = max(1, self.settings.div.divider());
1200        self.src_freq / div
1201    }
1202
1203    /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1204    ///
1205    /// The output off value (OOV) determines the logic level of a [GPIO](gpio)
1206    /// [`Pin`] (configured as a [`GclkIo`] output) when the [`Gclk`] is
1207    /// disabled **OR** the [`GclkOut`] is disabled.
1208    ///
1209    /// As mentioned in the [`Gclk`] documentation, configuration options are
1210    /// not usually applied until the call to [`Gclk::enable`]. However, because
1211    /// the OOV is relevant when the `Gclk` is *disabled*, we make an exception.
1212    /// When calling this function, the new OOV will take effect immediately.
1213    ///
1214    /// However, remember that the `Pin` is not controlled by the `Gclk` unless
1215    /// the `Pin` is configured in [`AlternateM`] mode. `Pin`s are automatically
1216    /// set to `AlternateM` mode when calling [`enable_gclk_out`], but by that
1217    /// point, the OOV is irrelevant. If you need the `Pin` to be set to its
1218    /// OOV, you must *manually* set it to `AlternateM` mode before constructing
1219    /// the `GclkOut`.
1220    ///
1221    /// [`enable_gclk_out`]: EnabledGclk::enable_gclk_out
1222    #[inline]
1223    pub fn output_off_value(mut self, high: bool) -> Self {
1224        self.settings.output_off_value = high;
1225        self.token.output_off_value(high);
1226        self
1227    }
1228
1229    /// Enable the [`Gclk`], so that it can be used as a clock [`Source`]
1230    ///
1231    /// As mentioned in the [`Gclk`] documentation, no hardware registers are
1232    /// actually modified until this call. Rather, the desired configuration is
1233    /// stored internally, and the [`Gclk`] is initialized and configured here
1234    /// according to the datasheet.
1235    ///
1236    /// The returned value is an [`EnabledGclk`] that can be used as a clock
1237    /// [`Source`] for other clocks.
1238    #[inline]
1239    pub fn enable(mut self) -> EnabledGclk<G, I> {
1240        self.token.configure(I::DYN, self.settings);
1241        self.token.enable();
1242        Enabled::new(self)
1243    }
1244}
1245
1246impl<G, I> EnabledGclk<G, I>
1247where
1248    G: GclkId,
1249    I: GclkSourceId,
1250{
1251    /// Disable the [`Gclk`]
1252    ///
1253    /// This method is only implemented for `N = U0`, which means the clock can
1254    /// only be disabled when no other clocks consume this [`Gclk`].
1255    #[inline]
1256    pub fn disable(mut self) -> Gclk<G, I> {
1257        self.0.token.disable();
1258        self.0
1259    }
1260}
1261
1262/// Special methods for an [`Enabled`] [`Gclk0`]
1263///
1264/// [`Gclk0`] is special, because it drives the processor's main clock, which
1265/// can never be disabled. As discussed in the [module-level documentation],
1266/// this fact is represented by permanently [`Increment`]ing the counter for
1267/// [`EnabledGclk0`]. Thus, the minimum value for `N` is `U1` and
1268/// [`EnabledGclk0`] can never be disabled.
1269///
1270/// These methods represent actions that can be taken when `N = U1`, i.e. the
1271/// [`Enabled`] counter is at its minimum value. This is the only time it's
1272/// safe to change the [`Gclk0`] [`Source`] or change its [`GclkDivider`] value.
1273///
1274/// [module-level documentation]: self
1275impl<I: GclkSourceId> EnabledGclk0<I, U1> {
1276    /// Swap [`Gclk0`] from one clock [`Source`] to another
1277    ///
1278    /// `Gclk0` will remain fully enabled during the swap.
1279    #[inline]
1280    pub fn swap_sources<O, N>(self, old: O, new: N) -> (EnabledGclk0<N::Id, U1>, O::Dec, N::Inc)
1281    where
1282        O: Source<Id = I> + Decrement,
1283        N: Source + Increment,
1284        N::Id: NotGclkIo,
1285    {
1286        let (gclk, _) = self.0.change_source((), new.freq());
1287        let enabled = Enabled::new(gclk);
1288        (enabled, old.dec(), new.inc())
1289    }
1290
1291    /// Swap [`Gclk0`] from one [`GclkIo`] [`Pin`] to another
1292    ///
1293    /// `Gclk0` will remain fully enabled during the swap.
1294    #[inline]
1295    pub fn swap_pins<P>(
1296        self,
1297        pin: P,
1298        freq: impl Into<Hertz>,
1299    ) -> (EnabledGclk0<P::Id, U1>, Pin<I, AlternateM>)
1300    where
1301        I: Gclk0Io,
1302        P: AnyPin,
1303        P::Id: Gclk0Io,
1304    {
1305        let pin = pin.into().into_mode();
1306        let (gclk, pin) = self.0.change_source(pin, freq.into());
1307        let enabled = Enabled::new(gclk);
1308        (enabled, pin)
1309    }
1310
1311    /// Swap [`Gclk0`] from a clock [`Source`] to a [`GclkIo`] [`Pin`]
1312    ///
1313    /// `Gclk0` will remain fully enabled during the swap.
1314    #[inline]
1315    pub fn swap_source_for_pin<S, P>(
1316        self,
1317        source: S,
1318        pin: P,
1319        freq: impl Into<Hertz>,
1320    ) -> (EnabledGclk0<P::Id, U1>, S::Dec)
1321    where
1322        S: Source<Id = I> + Decrement,
1323        P: AnyPin,
1324        P::Id: Gclk0Io,
1325    {
1326        let pin = pin.into().into_mode();
1327        let (gclk, _) = self.0.change_source(pin, freq.into());
1328        let enabled = Enabled::new(gclk);
1329        (enabled, source.dec())
1330    }
1331
1332    /// Swap [`Gclk0`] from a [`GclkIo`] [`Pin`] to a clock [`Source`]
1333    ///
1334    /// `Gclk0` will remain fully enabled during the swap.
1335    #[inline]
1336    #[allow(clippy::type_complexity)]
1337    pub fn swap_pin_for_source<S>(
1338        self,
1339        source: S,
1340    ) -> (EnabledGclk0<S::Id, U1>, Pin<I, AlternateM>, S::Inc)
1341    where
1342        I: Gclk0Io,
1343        S: Source + Increment,
1344        S::Id: NotGclkIo,
1345    {
1346        let (gclk, pin) = self.0.change_source((), source.freq());
1347        let enabled = Enabled::new(gclk);
1348        (enabled, pin, source.inc())
1349    }
1350
1351    /// Set the [`GclkDivider`] value for [`Gclk0`]
1352    ///
1353    /// See [`Gclk::div`] documentation for more details.
1354    #[inline]
1355    pub fn div(&mut self, div: GclkDiv8) {
1356        self.0.settings.div = div;
1357        self.0.token.set_div(div);
1358    }
1359
1360    /// Output a 50-50 duty cycle clock when using an odd [`GclkDivider`]
1361    #[inline]
1362    pub fn improve_duty_cycle(&mut self, flag: bool) {
1363        self.0.settings.improve_duty_cycle = flag;
1364        self.0.token.improve_duty_cycle(flag);
1365    }
1366
1367    /// Return the [`Gclk0`] frequency
1368    ///
1369    /// See [`Gclk::freq`] documentation for more details.
1370    #[inline]
1371    pub fn freq(&self) -> Hertz {
1372        self.0.freq()
1373    }
1374
1375    /// Set the state of [`GclkOut`] pins when [`GclkIo`] output is disabled
1376    ///
1377    /// See [`Gclk::output_off_value`] documentation for more details.
1378    #[inline]
1379    pub fn output_off_value(&mut self, high: bool) {
1380        self.0.settings.output_off_value = high;
1381        self.0.token.output_off_value(high);
1382    }
1383}
1384
1385//==============================================================================
1386// Source
1387//==============================================================================
1388
1389impl<G, I, N> Source for EnabledGclk<G, I, N>
1390where
1391    G: GclkId,
1392    I: GclkSourceId,
1393{
1394    type Id = G;
1395
1396    #[inline]
1397    fn freq(&self) -> Hertz {
1398        self.0.freq()
1399    }
1400}
1401
1402//==============================================================================
1403// Tokens
1404//==============================================================================
1405
1406seq!(N in 1..=11 {
1407    paste! {
1408        /// Set of [`GclkToken`]s representing the disabled [`Gclk`]s at
1409        /// power-on reset
1410        pub struct GclkTokens {
1411            #(
1412                /// [`GclkToken`] for
1413                #[doc = "[`Gclk" N "`]"]
1414                pub gclk~N: GclkToken<[<Gclk N Id>]>,
1415            )*
1416        }
1417
1418        impl GclkTokens {
1419            /// Create the set of [`GclkToken`]s
1420            ///
1421            /// # Safety
1422            ///
1423            /// All of the invariants required by `GclkToken::new` must be
1424            /// upheld here as well.
1425            #[inline]
1426            pub(super) unsafe fn new(nvmctrl: &mut Nvmctrl) -> Self {
1427                unsafe {
1428                    // Use auto wait states
1429                    nvmctrl.ctrla().modify(|_, w| w.autows().set_bit());
1430                    GclkTokens {
1431                        #( gclk~N: GclkToken::new(), )*
1432                    }
1433                }
1434            }
1435        }
1436    }
1437});
1438
1439//==============================================================================
1440// GclkOut
1441//==============================================================================
1442
1443/// A GPIO [`Pin`] configured as a [`Gclk`] output
1444///
1445/// The existence of this struct serves as proof that the corresponding [`Gclk`]
1446/// is [`Enabled`] and that it has been output to [`PinId`] `I`.
1447///
1448/// See the [module-level documentation](self) for an example of creating a
1449/// [`GclkOut`] from an [`EnabledGclk`].
1450pub struct GclkOut<I: GclkIo> {
1451    pin: Pin<I, AlternateM>,
1452    freq: Hertz,
1453}
1454
1455impl<G, I> GclkOut<I>
1456where
1457    G: GclkId,
1458    I: GclkIo<GclkId = G>,
1459{
1460    /// Return the frequency of the corresponding [`Gclk`]
1461    #[inline]
1462    pub fn freq(&self) -> Hertz {
1463        self.freq
1464    }
1465}
1466
1467impl<G, S, N> EnabledGclk<G, S, N>
1468where
1469    G: GclkId,
1470    S: NotGclkIo,
1471{
1472    /// Create and enable a [`GclkOut`]
1473    ///
1474    /// Enabling [`GclkIo`] output will [`Increment`] the `EnabledGclk`
1475    /// counter, which will prevent it from being disabled while the
1476    /// `GclkOut` exists.
1477    ///
1478    /// Note that a given [`Gclk`] can only use [`GclkIo`] for input **or**
1479    /// output, but not both simultaneously. The [`NotGclkIo`] trait exists to
1480    /// enforce this requirement.
1481    ///
1482    /// Finally, when a [`GclkOut`] is disabled, but the [`Pin`] is still in
1483    /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1484    /// the [`Gclk::output_off_value`] documentation for more details.
1485    #[inline]
1486    pub fn enable_gclk_out<P>(mut self, pin: P) -> (EnabledGclk<G, S, N::Inc>, GclkOut<P::Id>)
1487    where
1488        N: Increment,
1489        P: AnyPin,
1490        P::Id: GclkIo<GclkId = G>,
1491    {
1492        let pin = pin.into().into_mode();
1493        let freq = self.freq();
1494        self.0.token.enable_gclk_out();
1495        let gclk_out = GclkOut { pin, freq };
1496        (self.inc(), gclk_out)
1497    }
1498
1499    /// Disable a [`GclkOut`] and free its [`Pin`]
1500    ///
1501    /// Disabling [`GclkIo`] output will [`Decrement`] the [`EnabledGclk`]
1502    /// counter. When a [`GclkOut`] is disabled, but the [`Pin`] is still in
1503    /// [`AlternateM`] mode, it takes the "output off value" of the `Gclk`. See
1504    /// the [`Gclk::output_off_value`] documentation for more details.
1505    #[inline]
1506    pub fn disable_gclk_out<I>(
1507        mut self,
1508        gclk_out: GclkOut<I>,
1509    ) -> (EnabledGclk<G, S, N::Dec>, Pin<I, AlternateM>)
1510    where
1511        N: Decrement,
1512        I: GclkIo<GclkId = G>,
1513    {
1514        self.0.token.disable_gclk_out();
1515        (self.dec(), gclk_out.pin)
1516    }
1517}