components/
lsm303dlhc.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 the LSM303DLHC sensor.
6//!
7//! I2C Interface
8//!
9//! Usage
10//! -----
11//! ```rust
12//! let lsm303dlhc = components::lsm303dlhc::Lsm303dlhcI2CComponent::new(i2c_mux, board_kernel, driver_num)
13//!    .finalize(components::lsm303dlhc_component_static!());
14//!
15//! lsm303dlhc.configure(
16//!    lsm303dlhc::Lsm303dlhcAccelDataRate::DataRate25Hz,
17//!    false,
18//!    lsm303dlhc::Lsm303dlhcScale::Scale2G,
19//!    false,
20//!    true,
21//!    lsm303dlhc::Lsm303dlhcMagnetoDataRate::DataRate3_0Hz,
22//!    lsm303dlhc::Lsm303dlhcRange::Range4_7G,
23//! );
24//! ```
25use capsules_core::virtualizers::virtual_i2c::{I2CDevice, MuxI2C};
26use capsules_extra::lsm303dlhc::Lsm303dlhcI2C;
27use capsules_extra::lsm303xx;
28use core::mem::MaybeUninit;
29use kernel::component::Component;
30use kernel::hil::i2c;
31
32// Setup static space for the objects.
33#[macro_export]
34macro_rules! lsm303dlhc_component_static {
35    ($I:ty $(,)?) => {{
36        let buffer = kernel::static_buf!([u8; 8]);
37        let accelerometer_i2c =
38            kernel::static_buf!(capsules_core::virtualizers::virtual_i2c::I2CDevice<$I>);
39        let magnetometer_i2c =
40            kernel::static_buf!(capsules_core::virtualizers::virtual_i2c::I2CDevice<$I>);
41        let lsm303dlhc = kernel::static_buf!(
42            capsules_extra::lsm303dlhc::Lsm303dlhcI2C<
43                'static,
44                capsules_core::virtualizers::virtual_i2c::I2CDevice<$I>,
45            >
46        );
47
48        (accelerometer_i2c, magnetometer_i2c, buffer, lsm303dlhc)
49    };};
50}
51
52pub struct Lsm303dlhcI2CComponent<I: 'static + i2c::I2CMaster<'static>> {
53    i2c_mux: &'static MuxI2C<'static, I>,
54    accelerometer_i2c_address: u8,
55    magnetometer_i2c_address: u8,
56    board_kernel: &'static kernel::Kernel,
57    driver_num: usize,
58}
59
60impl<I: 'static + i2c::I2CMaster<'static>> Lsm303dlhcI2CComponent<I> {
61    pub fn new(
62        i2c_mux: &'static MuxI2C<'static, I>,
63        accelerometer_i2c_address: Option<u8>,
64        magnetometer_i2c_address: Option<u8>,
65        board_kernel: &'static kernel::Kernel,
66        driver_num: usize,
67    ) -> Lsm303dlhcI2CComponent<I> {
68        Lsm303dlhcI2CComponent {
69            i2c_mux,
70            accelerometer_i2c_address: accelerometer_i2c_address
71                .unwrap_or(lsm303xx::ACCELEROMETER_BASE_ADDRESS),
72            magnetometer_i2c_address: magnetometer_i2c_address
73                .unwrap_or(lsm303xx::MAGNETOMETER_BASE_ADDRESS),
74            board_kernel,
75            driver_num,
76        }
77    }
78}
79
80impl<I: 'static + i2c::I2CMaster<'static>> Component for Lsm303dlhcI2CComponent<I> {
81    type StaticInput = (
82        &'static mut MaybeUninit<I2CDevice<'static, I>>,
83        &'static mut MaybeUninit<I2CDevice<'static, I>>,
84        &'static mut MaybeUninit<[u8; 8]>,
85        &'static mut MaybeUninit<Lsm303dlhcI2C<'static, I2CDevice<'static, I>>>,
86    );
87    type Output = &'static Lsm303dlhcI2C<'static, I2CDevice<'static, I>>;
88
89    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
90        let grant_cap =
91            kernel::create_capability!(kernel::capabilities::MemoryAllocationCapability);
92
93        let buffer = static_buffer.2.write([0; 8]);
94
95        let accelerometer_i2c = static_buffer
96            .0
97            .write(I2CDevice::new(self.i2c_mux, self.accelerometer_i2c_address));
98        let magnetometer_i2c = static_buffer
99            .1
100            .write(I2CDevice::new(self.i2c_mux, self.magnetometer_i2c_address));
101
102        let lsm303dlhc = static_buffer.3.write(Lsm303dlhcI2C::new(
103            accelerometer_i2c,
104            magnetometer_i2c,
105            buffer,
106            self.board_kernel.create_grant(self.driver_num, &grant_cap),
107        ));
108        accelerometer_i2c.set_client(lsm303dlhc);
109        magnetometer_i2c.set_client(lsm303dlhc);
110
111        lsm303dlhc
112    }
113}