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