components/
adc.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//! Components for using ADC capsules.
6
7use capsules_core::adc::AdcDedicated;
8use capsules_core::adc::AdcVirtualized;
9use capsules_core::virtualizers::virtual_adc::{AdcDevice, MuxAdc};
10use core::mem::MaybeUninit;
11use kernel::capabilities;
12use kernel::component::Component;
13use kernel::create_capability;
14use kernel::hil::adc;
15
16#[macro_export]
17macro_rules! adc_mux_component_static {
18    ($A:ty $(,)?) => {{
19        kernel::static_buf!(capsules_core::virtualizers::virtual_adc::MuxAdc<'static, $A>)
20    };};
21}
22
23#[macro_export]
24macro_rules! adc_component_static {
25    ($A:ty $(,)?) => {{
26        kernel::static_buf!(capsules_core::virtualizers::virtual_adc::AdcDevice<'static, $A>)
27    };};
28}
29
30#[macro_export]
31macro_rules! adc_syscall_component_helper {
32    ($($P:expr),+ $(,)?) => {{
33        use kernel::count_expressions;
34        use kernel::static_init;
35        const NUM_DRIVERS: usize = count_expressions!($($P),+);
36
37        let drivers = static_init!(
38            [&'static dyn kernel::hil::adc::AdcChannel; NUM_DRIVERS],
39            [
40                $($P,)*
41            ]
42        );
43        let adc_virtualized = kernel::static_buf!(capsules_core::adc::AdcVirtualized<'static>);
44        (adc_virtualized, drivers)
45    };};
46}
47
48#[macro_export]
49macro_rules! adc_dedicated_component_static {
50    ($A:ty $(,)?) => {{
51        let adc = kernel::static_buf!(capsules_core::adc::AdcDedicated<'static, $A>);
52        let buffer1 = kernel::static_buf!([u16; capsules_core::adc::BUF_LEN]);
53        let buffer2 = kernel::static_buf!([u16; capsules_core::adc::BUF_LEN]);
54        let buffer3 = kernel::static_buf!([u16; capsules_core::adc::BUF_LEN]);
55
56        (adc, buffer1, buffer2, buffer3)
57    };};
58}
59
60pub struct AdcMuxComponent<A: 'static + adc::Adc<'static>> {
61    adc: &'static A,
62}
63
64impl<A: 'static + adc::Adc<'static>> AdcMuxComponent<A> {
65    pub fn new(adc: &'static A) -> Self {
66        AdcMuxComponent { adc }
67    }
68}
69
70impl<A: 'static + adc::Adc<'static>> Component for AdcMuxComponent<A> {
71    type StaticInput = &'static mut MaybeUninit<MuxAdc<'static, A>>;
72    type Output = &'static MuxAdc<'static, A>;
73
74    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
75        let adc_mux = static_buffer.write(MuxAdc::new(self.adc));
76
77        self.adc.set_client(adc_mux);
78
79        adc_mux
80    }
81}
82
83pub struct AdcComponent<A: 'static + adc::Adc<'static>> {
84    adc_mux: &'static MuxAdc<'static, A>,
85    channel: A::Channel,
86}
87
88impl<A: 'static + adc::Adc<'static>> AdcComponent<A> {
89    pub fn new(mux: &'static MuxAdc<'static, A>, channel: A::Channel) -> Self {
90        AdcComponent {
91            adc_mux: mux,
92            channel,
93        }
94    }
95}
96
97impl<A: 'static + adc::Adc<'static>> Component for AdcComponent<A> {
98    type StaticInput = &'static mut MaybeUninit<AdcDevice<'static, A>>;
99    type Output = &'static AdcDevice<'static, A>;
100
101    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
102        let adc_device = static_buffer.write(AdcDevice::new(self.adc_mux, self.channel));
103
104        adc_device.add_to_mux();
105
106        adc_device
107    }
108}
109
110pub struct AdcVirtualComponent {
111    board_kernel: &'static kernel::Kernel,
112    driver_num: usize,
113}
114
115impl AdcVirtualComponent {
116    pub fn new(board_kernel: &'static kernel::Kernel, driver_num: usize) -> AdcVirtualComponent {
117        AdcVirtualComponent {
118            board_kernel,
119            driver_num,
120        }
121    }
122}
123
124impl Component for AdcVirtualComponent {
125    type StaticInput = (
126        &'static mut MaybeUninit<AdcVirtualized<'static>>,
127        &'static [&'static dyn kernel::hil::adc::AdcChannel<'static>],
128    );
129    type Output = &'static capsules_core::adc::AdcVirtualized<'static>;
130
131    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
132        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
133        let grant_adc = self.board_kernel.create_grant(self.driver_num, &grant_cap);
134
135        let adc = static_buffer
136            .0
137            .write(capsules_core::adc::AdcVirtualized::new(
138                static_buffer.1,
139                grant_adc,
140            ));
141
142        for driver in static_buffer.1 {
143            kernel::hil::adc::AdcChannel::set_client(*driver, adc);
144        }
145
146        adc
147    }
148}
149
150pub type AdcDedicatedComponentType<A> = capsules_core::adc::AdcDedicated<'static, A>;
151
152pub struct AdcDedicatedComponent<
153    A: kernel::hil::adc::Adc<'static> + kernel::hil::adc::AdcHighSpeed<'static> + 'static,
154> {
155    adc: &'static A,
156    channels: &'static [A::Channel],
157    board_kernel: &'static kernel::Kernel,
158    driver_num: usize,
159}
160
161impl<A: kernel::hil::adc::Adc<'static> + kernel::hil::adc::AdcHighSpeed<'static> + 'static>
162    AdcDedicatedComponent<A>
163{
164    pub fn new(
165        adc: &'static A,
166        channels: &'static [A::Channel],
167        board_kernel: &'static kernel::Kernel,
168        driver_num: usize,
169    ) -> AdcDedicatedComponent<A> {
170        AdcDedicatedComponent {
171            adc,
172            channels,
173            board_kernel,
174            driver_num,
175        }
176    }
177}
178
179impl<A: kernel::hil::adc::Adc<'static> + kernel::hil::adc::AdcHighSpeed<'static> + 'static>
180    Component for AdcDedicatedComponent<A>
181{
182    type StaticInput = (
183        &'static mut MaybeUninit<AdcDedicated<'static, A>>,
184        &'static mut MaybeUninit<[u16; capsules_core::adc::BUF_LEN]>,
185        &'static mut MaybeUninit<[u16; capsules_core::adc::BUF_LEN]>,
186        &'static mut MaybeUninit<[u16; capsules_core::adc::BUF_LEN]>,
187    );
188    type Output = &'static AdcDedicated<'static, A>;
189
190    fn finalize(self, s: Self::StaticInput) -> Self::Output {
191        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
192
193        let buffer1 = s.1.write([0; capsules_core::adc::BUF_LEN]);
194        let buffer2 = s.2.write([0; capsules_core::adc::BUF_LEN]);
195        let buffer3 = s.3.write([0; capsules_core::adc::BUF_LEN]);
196
197        let adc = s.0.write(AdcDedicated::new(
198            self.adc,
199            self.board_kernel.create_grant(self.driver_num, &grant_cap),
200            self.channels,
201            buffer1,
202            buffer2,
203            buffer3,
204        ));
205        self.adc.set_client(adc);
206        self.adc.set_highspeed_client(adc);
207
208        adc
209    }
210}