lpc8xx_hal/i2c/
clock.rs

1use core::marker::PhantomData;
2
3use crate::syscon::{self, clock_source::PeripheralClockSelector};
4
5/// Contains the clock configuration for an I2C instance
6pub struct Clock<Clock> {
7    pub(crate) divval: u16,
8    pub(crate) mstsclhigh: u8,
9    pub(crate) mstscllow: u8,
10    pub(crate) _clock: PhantomData<Clock>,
11}
12
13impl<C> Clock<C>
14where
15    C: ClockSource,
16{
17    /// Create the clock config for the I2C peripheral
18    ///
19    /// `mstclhigh` and `mstcllow` have to be between 2-9.
20    pub fn new(_: &C, divval: u16, mstsclhigh: u8, mstscllow: u8) -> Self {
21        assert!(mstsclhigh > 1 && mstsclhigh < 10);
22        assert!(mstscllow > 1 && mstscllow < 10);
23        Self {
24            divval,
25            mstsclhigh: mstsclhigh - 2,
26            mstscllow: mstscllow - 2,
27            _clock: PhantomData,
28        }
29    }
30}
31
32/// Implemented for I2C clock sources
33pub trait ClockSource: private::Sealed {
34    /// Select the clock source
35    ///
36    /// This method is used by the I2C API internally. It should not be relevant
37    /// to most users.
38    ///
39    /// The `selector` argument should not be required to implement this trait,
40    /// but it makes sure that the caller has access to the peripheral they are
41    /// selecting the clock for.
42    fn select<S>(selector: &S, handle: &mut syscon::Handle)
43    where
44        S: PeripheralClockSelector;
45}
46
47#[cfg(feature = "82x")]
48mod target {
49    use core::marker::PhantomData;
50
51    use crate::syscon;
52
53    use super::{Clock, ClockSource};
54
55    impl super::private::Sealed for () {}
56
57    impl ClockSource for () {
58        fn select<S>(_: &S, _: &mut syscon::Handle) {
59            // nothing to do; `()` represents the clock that is selected by
60            // default
61        }
62    }
63
64    impl Clock<()> {
65        /// Create a new I2C clock configuration for 400 kHz
66        ///
67        /// Assumes the internal oscillator runs at 12 MHz.
68        pub fn new_400khz() -> Self {
69            Self {
70                divval: 5,
71                mstsclhigh: 0,
72                mstscllow: 1,
73                _clock: PhantomData,
74            }
75        }
76    }
77}
78
79#[cfg(feature = "845")]
80mod target {
81    use core::marker::PhantomData;
82
83    use crate::syscon::{
84        self,
85        clock_source::{PeripheralClock, PeripheralClockSelector},
86        IOSC,
87    };
88
89    use super::{Clock, ClockSource};
90
91    impl<T> super::private::Sealed for T where T: PeripheralClock {}
92    impl<T> ClockSource for T
93    where
94        T: PeripheralClock,
95    {
96        fn select<S>(selector: &S, handle: &mut syscon::Handle)
97        where
98            S: PeripheralClockSelector,
99        {
100            T::select(selector, handle);
101        }
102    }
103
104    impl Clock<IOSC> {
105        /// Create a new I2C clock configuration for 400 kHz
106        ///
107        /// Assumes the internal oscillator runs at 12 MHz.
108        pub fn new_400khz() -> Self {
109            Self {
110                divval: 5,
111                mstsclhigh: 0,
112                mstscllow: 1,
113                _clock: PhantomData,
114            }
115        }
116    }
117}
118
119mod private {
120    pub trait Sealed {}
121}