components/
analog_comparator.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component for initializing an Analog Comparator.
6//!
7//! This provides one Component, AcComponent, which implements a userspace
8//! syscall interface to a passed analog comparator driver.
9//!
10//! Usage
11//! -----
12//! ```rust
13//! let analog_comparator = components::analog_comparator::AnalogComparatorComponent::new(
14//!     &sam4l::acifc::ACIFC,
15//!     components::analog_comparator_component_helper!(
16//!         <sam4l::acifc::Acifc as kernel::hil::analog_comparator::AnalogComparator>::Channel,
17//!         &sam4l::acifc::CHANNEL_AC0,
18//!         &sam4l::acifc::CHANNEL_AC1,
19//!         &sam4l::acifc::CHANNEL_AC2,
20//!         &sam4l::acifc::CHANNEL_AC3
21//!     ),
22//! )
23//! .finalize(components::analog_comparator_component_static!(sam4l::acifc::Acifc));
24//! ```
25
26use capsules_extra::analog_comparator::AnalogComparator;
27use core::mem::MaybeUninit;
28use kernel::capabilities;
29use kernel::component::Component;
30use kernel::create_capability;
31
32#[macro_export]
33macro_rules! analog_comparator_component_helper {
34    ($Channel:ty, $($P:expr),+ $(,)?) => {{
35        use kernel::count_expressions;
36        use kernel::static_init;
37        const NUM_CHANNELS: usize = count_expressions!($($P),+);
38
39        static_init!(
40            [&'static $Channel; NUM_CHANNELS],
41            [
42                $($P,)*
43            ]
44        )
45    };};
46}
47
48#[macro_export]
49macro_rules! analog_comparator_component_static {
50    ($AC:ty $(,)?) => {{
51        kernel::static_buf!(capsules_extra::analog_comparator::AnalogComparator<'static, $AC>)
52    };};
53}
54
55pub struct AnalogComparatorComponent<
56    AC: 'static + kernel::hil::analog_comparator::AnalogComparator<'static>,
57> {
58    comp: &'static AC,
59    ac_channels: &'static [&'static AC::Channel],
60    board_kernel: &'static kernel::Kernel,
61    driver_num: usize,
62}
63
64impl<AC: 'static + kernel::hil::analog_comparator::AnalogComparator<'static>>
65    AnalogComparatorComponent<AC>
66{
67    pub fn new(
68        comp: &'static AC,
69        ac_channels: &'static [&'static AC::Channel],
70        board_kernel: &'static kernel::Kernel,
71        driver_num: usize,
72    ) -> Self {
73        Self {
74            comp,
75            ac_channels,
76            board_kernel,
77            driver_num,
78        }
79    }
80}
81
82impl<AC: 'static + kernel::hil::analog_comparator::AnalogComparator<'static>> Component
83    for AnalogComparatorComponent<AC>
84{
85    type StaticInput = &'static mut MaybeUninit<AnalogComparator<'static, AC>>;
86    type Output = &'static AnalogComparator<'static, AC>;
87
88    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
89        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
90        let grant_ac = self.board_kernel.create_grant(self.driver_num, &grant_cap);
91
92        let analog_comparator =
93            static_buffer.write(AnalogComparator::new(self.comp, self.ac_channels, grant_ac));
94        self.comp.set_client(analog_comparator);
95
96        analog_comparator
97    }
98}