#![no_std]
#![doc(html_root_url = "https://docs.rs/adxl343/0.8.0")]
#![forbid(unsafe_code)]
#![warn(missing_docs, rust_2018_idioms, unused_qualifications)]
mod register;
pub use crate::register::{DataFormatFlags, DataFormatRange};
pub use accelerometer;
use embedded_hal as hal;
use crate::register::Register;
#[cfg(feature = "u16x3")]
use accelerometer::vector::U16x3;
#[cfg(feature = "i16x3")]
use accelerometer::{
vector::{F32x3, I16x3},
Accelerometer,
};
use accelerometer::{Error, ErrorKind, RawAccelerometer};
use core::fmt::Debug;
use hal::blocking::i2c::{Write, WriteRead};
pub const ADDRESS: u8 = 0x53;
pub const DEVICE_ID: u8 = 0xE5;
pub struct Adxl343<I2C> {
i2c: I2C,
data_format: DataFormatFlags,
}
impl<I2C, E> Adxl343<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
E: Debug,
{
pub fn new(i2c: I2C) -> Result<Self, Error<E>> {
Self::new_with_data_format(i2c, DataFormatFlags::default())
}
pub fn new_with_data_format<F>(i2c: I2C, data_format: F) -> Result<Self, Error<E>>
where
F: Into<DataFormatFlags>,
{
let mut adxl343 = Adxl343 {
i2c,
data_format: data_format.into(),
};
if adxl343.get_device_id()? != DEVICE_ID {
ErrorKind::Device.err()?;
}
adxl343.data_format(adxl343.data_format)?;
adxl343.write_register(Register::INT_ENABLE, 0)?;
adxl343.write_register(Register::THRESH_TAP, 20)?;
adxl343.write_register(Register::DUR, 50)?;
adxl343.write_register(Register::LATENT, 0)?;
adxl343.write_register(Register::WINDOW, 0)?;
adxl343.write_register(Register::TAP_AXES, 0x7)?;
adxl343.write_register(Register::POWER_CTL, 0x08)?;
Ok(adxl343)
}
pub fn data_format<F>(&mut self, data_format: F) -> Result<(), Error<E>>
where
F: Into<DataFormatFlags>,
{
let f = data_format.into();
let input = [Register::DATA_FORMAT.addr(), f.bits()];
self.i2c.write(ADDRESS, &input)?;
self.data_format = f;
Ok(())
}
pub fn write_register(&mut self, register: Register, value: u8) -> Result<(), Error<E>> {
assert_ne!(
register,
Register::DATA_FORMAT,
"set data format with Adxl343::data_format"
);
debug_assert!(!register.read_only(), "can't write to read-only register");
self.i2c.write(ADDRESS, &[register.addr(), value])?;
Ok(())
}
pub fn write_read_register(&mut self, register: Register, buffer: &mut [u8]) -> Result<(), E> {
self.i2c.write_read(ADDRESS, &[register.addr()], buffer)
}
fn get_device_id(&mut self) -> Result<u8, E> {
let input = [Register::DEVID.addr()];
let mut output = [0u8];
self.i2c.write_read(ADDRESS, &input, &mut output)?;
Ok(output[0])
}
#[cfg(feature = "i16x3")]
fn write_read_i16(&mut self, register: Register) -> Result<i16, E> {
let mut buffer = [0u8; 2];
self.write_read_register(register, &mut buffer)?;
Ok(i16::from_be_bytes(buffer))
}
#[cfg(feature = "u16x3")]
fn write_read_u16(&mut self, register: Register) -> Result<u16, E> {
let mut buffer = [0u8; 2];
self.write_read_register(register, &mut buffer)?;
Ok(u16::from_le_bytes(buffer))
}
}
#[cfg(feature = "i16x3")]
impl<I2C, E> Accelerometer for Adxl343<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
E: Debug,
{
type Error = E;
fn accel_norm(&mut self) -> Result<F32x3, Error<E>> {
let raw_data: I16x3 = self.accel_raw()?;
let range: f32 = self.data_format.range().into();
let x = (raw_data.x as f32 / core::i16::MAX as f32) * range;
let y = (raw_data.y as f32 / core::i16::MAX as f32) * range;
let z = (raw_data.z as f32 / core::i16::MAX as f32) * range;
Ok(F32x3::new(x, y, z))
}
fn sample_rate(&mut self) -> Result<f32, Error<Self::Error>> {
Ok(100.0)
}
}
#[cfg(feature = "i16x3")]
impl<I2C, E> RawAccelerometer<I16x3> for Adxl343<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
E: Debug,
{
type Error = E;
fn accel_raw(&mut self) -> Result<I16x3, Error<E>> {
if self.data_format.contains(DataFormatFlags::JUSTIFY) {
return Err(Error::new(ErrorKind::Mode));
}
let x = self.write_read_i16(Register::DATAX0)?;
let y = self.write_read_i16(Register::DATAY0)?;
let z = self.write_read_i16(Register::DATAZ0)?;
Ok(I16x3::new(x, y, z))
}
}
#[cfg(feature = "u16x3")]
impl<I2C, E> RawAccelerometer<U16x3> for Adxl343<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
E: Debug,
{
type Error = E;
fn accel_raw(&mut self) -> Result<U16x3, Error<E>> {
if !self.data_format.contains(DataFormatFlags::JUSTIFY) {
return Err(Error::new(ErrorKind::Mode));
}
let x = self.write_read_u16(Register::DATAX0)?;
let y = self.write_read_u16(Register::DATAY0)?;
let z = self.write_read_u16(Register::DATAZ0)?;
Ok(U16x3::new(x, y, z))
}
}