iis2mdc/
lib.rs

1//! This is a simple driver for ST's `iis2mdc` sensor.
2//!
3//! # Quick Start
4//! To declare a sensor is pretty simple:
5//!
6//! ```rust
7//! let sensor = Iis2mdc::new(&mut i2c).unwrap()
8//! ```
9//!
10//! All registers have the bits addressed by their function, for example here se set the `BOOT` register in the `CTRL_3C` register to `1`
11//!
12//! ```rust
13//! sensor.cfg_reg_a.set_reboot(i2c, true).unwrap();
14//! ```
15//!
16//! For bits that operate together, they have their custom type abstracted. For example, to set the accelerometer data rate you have to operate 4 bits. But here you just have to specify your desired data rate and the driver takes care of it.
17//!
18//! ```rust
19//! // Sets the following bits
20//! // ODR_0 to 1
21//! // ODR_1 to 0
22//!
23//! sensor
24//!     .cfg_reg_a
25//!     .set_data_rate(i2c, iis2mdc::cfg_reg_a::Odr::Hz50)
26//!     .unwrap();
27//! ```
28//!
29//! # Reference
30//!
31//!- [Sensor page](https://www.st.com/en/mems-and-sensors/iis2mdc.html)
32//!- [Datasheet](https://www.st.com/resource/en/datasheet/iis2mdc.pdf)
33
34#![no_std]
35
36pub mod cfg_reg_a;
37pub mod cfg_reg_b;
38pub mod cfg_reg_c;
39
40use cfg_reg_a::CfgRegA;
41use cfg_reg_b::CfgRegB;
42use cfg_reg_c::CfgRegC;
43
44/// Datasheed write address for the device. (3Ch) ??
45/// My sample only answers on 0x1e
46pub const I2C_ADDRESS: u8 = 0x1eu8;
47
48trait Register {
49    fn read<I2C>(&self, i2c: &mut I2C, reg_addr: u8) -> Result<u8, I2C::Error>
50    where
51        I2C: embedded_hal::i2c::I2c,
52    {
53        let mut data: [u8; 1] = [0];
54        i2c.write_read(I2C_ADDRESS, &[reg_addr], &mut data)?;
55        Ok(data[0])
56    }
57
58    fn write<I2C>(&self, i2c: &mut I2C, reg_addr: u8, bits: u8) -> Result<(), I2C::Error>
59    where
60        I2C: embedded_hal::i2c::I2c,
61    {
62        i2c.write(I2C_ADDRESS, &[reg_addr, bits])
63    }
64}
65
66pub struct Iis2mdc {
67    pub cfg_reg_a: CfgRegA,
68    pub cfg_reg_b: CfgRegB,
69    pub cfg_reg_c: CfgRegC,
70}
71
72impl Iis2mdc {
73    pub fn new<I2C>(i2c: &mut I2C) -> Result<Iis2mdc, I2C::Error>
74    where
75        I2C: embedded_hal::i2c::I2c,
76    {
77        let mut registers = [0u8; 3];
78        i2c.write_read(I2C_ADDRESS, &[0x60], &mut registers)?;
79
80        let cfg_reg_a = CfgRegA::new(registers[0]);
81        let cfg_reg_b = CfgRegB::new(registers[1]);
82        let cfg_reg_c = CfgRegC::new(registers[2]);
83
84        let iis2mdc = Iis2mdc {
85            cfg_reg_a,
86            cfg_reg_b,
87            cfg_reg_c,
88        };
89
90        Ok(iis2mdc)
91    }
92
93    pub fn get_temperature<I2C>(&mut self, i2c: &mut I2C) -> Result<f32, I2C::Error>
94    where
95        I2C: embedded_hal::i2c::I2c,
96    {
97        let mut measurements = [0u8; 2];
98        i2c.write_read(I2C_ADDRESS, &[0x6e], &mut measurements)?;
99
100        let raw_temp = (measurements[1] as i16) << 8 | measurements[0] as i16;
101        let temp: f32 = (raw_temp as f32 / 256.0) + 25.0;
102
103        Ok(temp)
104    }
105
106    pub fn get_measurements<I2C>(&mut self, i2c: &mut I2C) -> Result<[f64; 3], I2C::Error>
107    where
108        I2C: embedded_hal::i2c::I2c,
109    {
110        let mut measurements = [0u8; 6];
111        i2c.write_read(I2C_ADDRESS, &[0x68], &mut measurements)?;
112
113        let raw_mag_x = (measurements[1] as i16) << 8 | (measurements[0] as i16);
114        let raw_mag_y = (measurements[3] as i16) << 8 | (measurements[2] as i16);
115        let raw_mag_z = (measurements[5] as i16) << 8 | (measurements[4] as i16);
116
117        let mag_x = raw_mag_x as f64;
118        let mag_y = raw_mag_y as f64;
119        let mag_z = raw_mag_z as f64;
120
121        Ok([mag_x, mag_y, mag_z])
122    }
123}