1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
//! This is a platform agnostic Rust driver for the LSM303AGR ultra-compact
//! high-performance eCompass module: ultra-low-power 3D accelerometer and
//! 3D magnetometer using the [`embedded-hal`] traits.
//!
//! [`embedded-hal`]: https://github.com/rust-embedded/embedded-hal
//!
//! This driver allows you to:
//! - Connect through I2C or SPI. See: [`new_with_i2c()`](Lsm303agr::new_with_i2c) and [`new_with_spi()`](Lsm303agr::new_with_spi) .
//! - Initialize the device. See: [`init()`](Lsm303agr::init).
//! - Accelerometer:
//! - Read measured acceleration. See: [`acceleration()`](Lsm303agr::acceleration).
//! - Get accelerometer status. See: [`accel_status()`](Lsm303agr::accel_status).
//! - Set accelerometer mode and output data rate. See: [`set_accel_mode_and_odr()`](Lsm303agr::set_accel_mode_and_odr).
//! - Set accelerometer scale. See: [`set_accel_scale()`](Lsm303agr::set_accel_scale).
//! - Get accelerometer ID. See: [`accelerometer_id()`](Lsm303agr::accelerometer_id).
//! - Get temperature sensor status. See: [`temperature_status()`](Lsm303agr::temperature_status).
//! - Read measured temperature. See: [`temperature()`](Lsm303agr::temperature).
//! - Configure FIFO. See: [`acc_set_fifo_mode()`](Lsm303agr::acc_set_fifo_mode).
//! - Enable/disable interrupts. See: [`acc_enable_interrupt()`](Lsm303agr::acc_enable_interrupt).
//! - Magnetometer:
//! - Get the magnetometer status. See: [`mag_status()`](Lsm303agr::mag_status).
//! - Change into continuous/one-shot mode. See: [`into_mag_continuous()`](Lsm303agr::into_mag_continuous).
//! - Read measured magnetic field. See: [`magnetic_field()`](Lsm303agr::magnetic_field).
//! - Set magnetometer mode and output data rate. See: [`set_mag_mode_and_odr()`](Lsm303agr::set_mag_mode_and_odr).
//! - Get magnetometer ID. See: [`magnetometer_id()`](Lsm303agr::magnetometer_id).
//! - Enable/disable magnetometer built in offset cancellation. See: [`enable_mag_offset_cancellation()`](Lsm303agr::enable_mag_offset_cancellation).
//! - Enable/disable magnetometer low-pass filter. See: [`mag_enable_low_pass_filter()`](Lsm303agr::mag_enable_low_pass_filter).
//!
//! <!-- TODO
//! [Introductory blog post](TODO)
//! -->
//!
//! ## The devices
//!
//! The LSM303AGR is an ultralow-power high-performance system-in-package featuring a
//! 3-axis digital linear acceleration sensor and a 3-axis digital magnetic sensor.
//!
//! The LSM303AGR has linear acceleration full scales of ±2g/±4g/±8g/±16g and a magnetic field
//! dynamic range of ±50 gauss. The LSM303AGR includes an I²C serial bus
//! interface that supports standard, fast mode, fast mode plus, and high-speed
//! (100 kHz, 400 kHz, 1 MHz, and 3.4 MHz) and an SPI serial standard interface.
//!
//! The system can be configured to generate an interrupt signal for free-fall,
//! motion detection, and magnetic field detection. The magnetic and accelerometer blocks can be
//! enabled or put into power-down mode separately.
//!
//! Documents: [Datasheet](https://www.st.com/resource/en/datasheet/lsm303agr.pdf) - [Application note](https://www.st.com/resource/en/application_note/dm00265383-ultracompact-highperformance-ecompass-module-based-on-the-lsm303agr-stmicroelectronics.pdf)
//!
//!
//! ## Usage examples (see also examples folder)
//!
//! To use this driver, import this crate and an `embedded_hal` implementation,
//! then instantiate the appropriate device.
//!
//! Please find additional examples using hardware in this repository: [driver-examples]
//!
//! [driver-examples]: https://github.com/eldruin/driver-examples
//!
//! ### Connect through I2C, initialize and take some measurements
//!
//! ```no_run
//! # #[cfg(target_os = "linux")] {
//! use linux_embedded_hal::{Delay, I2cdev};
//! use lsm303agr::{AccelMode, AccelOutputDataRate, Lsm303agr};
//!
//! let dev = I2cdev::new("/dev/i2c-1").unwrap();
//! let mut sensor = Lsm303agr::new_with_i2c(dev);
//!
//! sensor.init().unwrap();
//! sensor.set_accel_mode_and_odr(&mut Delay, AccelMode::Normal, AccelOutputDataRate::Hz10).unwrap();
//!
//! loop {
//! if sensor.accel_status().unwrap().xyz_new_data() {
//! let data = sensor.acceleration().unwrap();
//! println!("Acceleration: x {} y {} z {}", data.x_mg(), data.y_mg(), data.z_mg());
//! }
//! }
//! # }
//! ```
//!
//! ### Connect through SPI, initialize and take some measurements
//!
//! ```no_run
//! # #[cfg(target_os = "linux")] {
//! use linux_embedded_hal::{Delay, SpidevDevice};
//! use lsm303agr::{AccelMode, AccelOutputDataRate, Lsm303agr};
//!
//! let accel_dev = SpidevDevice::open("/dev/spidev0.0").unwrap();
//! let mag_dev = SpidevDevice::open("/dev/spidev0.1").unwrap();
//! let mut sensor = Lsm303agr::new_with_spi(accel_dev, mag_dev);
//!
//! sensor.init().unwrap();
//! sensor.set_accel_mode_and_odr(&mut Delay, AccelMode::Normal, AccelOutputDataRate::Hz10).unwrap();
//!
//! loop {
//! if sensor.accel_status().unwrap().xyz_new_data() {
//! let data = sensor.acceleration().unwrap();
//! println!("Acceleration: x {} y {} z {}", data.x_mg(), data.y_mg(), data.z_mg());
//! }
//! }
//! # }
//! ```
#![deny(unsafe_code, missing_docs)]
#![no_std]
use core::marker::PhantomData;
mod accel_mode_and_odr;
mod device_impl;
pub mod interface;
mod mag_mode_change;
mod magnetometer;
mod types;
pub use crate::types::{
mode, AccelMode, AccelOutputDataRate, AccelScale, Acceleration, AccelerometerId, Error,
FifoMode, Interrupt, MagMode, MagOutputDataRate, MagneticField, MagnetometerId,
ModeChangeError, Status, Temperature, TemperatureStatus,
};
mod register_address;
use crate::register_address::{
CfgRegAM, CfgRegBM, CfgRegCM, CtrlReg1A, CtrlReg3A, CtrlReg4A, CtrlReg5A, FifoCtrlRegA,
TempCfgRegA,
};
/// LSM303AGR device driver
#[derive(Debug)]
pub struct Lsm303agr<DI, MODE> {
/// Digital interface: I2C or SPI
iface: DI,
ctrl_reg1_a: CtrlReg1A,
ctrl_reg3_a: CtrlReg3A,
ctrl_reg4_a: CtrlReg4A,
ctrl_reg5_a: CtrlReg5A,
cfg_reg_a_m: CfgRegAM,
cfg_reg_b_m: CfgRegBM,
cfg_reg_c_m: CfgRegCM,
temp_cfg_reg_a: TempCfgRegA,
fifo_ctrl_reg_a: FifoCtrlRegA,
accel_odr: Option<AccelOutputDataRate>,
_mag_mode: PhantomData<MODE>,
}
mod private {
use crate::interface;
pub trait Sealed {}
impl<SPIXL, SPIMAG> Sealed for interface::SpiInterface<SPIXL, SPIMAG> {}
impl<I2C> Sealed for interface::I2cInterface<I2C> {}
}