#![no_std]
#![deny(missing_docs)]
#![deny(warnings)]
extern crate embedded_hal as hal;
use core::fmt;
use hal::blocking::i2c::{Write, WriteRead};
pub struct Bma222e<I2C> {
device: I2C,
}
pub const ADDRESS: u8 = 0x19;
pub const IDENTIFIER: u8 = 0xF8;
const EEPROM_LENGTH: usize = 5;
const REG_CHIPID: u8 = 0x00;
const REG_XAXIS: u8 = 0x02;
const REG_YAXIS: u8 = 0x04;
const REG_ZAXIS: u8 = 0x06;
const REG_TEMPERATURE: u8 = 0x08;
const REG_FIFO_STATUS: u8 = 0x0E;
const REG_RESET: u8 = 0x14;
const REG_EEPROM_CONTROL: u8 = 0x33;
const REG_EEPROM_START: u8 = 0x38;
const REG_FIFO_CONFIG: u8 = 0x3E;
const REG_FIFO_DATA: u8 = 0x3F;
pub enum FIFOConfig {
BYPASS = 0,
FIFO = 1,
STREAM = 2,
}
#[derive(Copy, Clone)]
pub struct AxisData {
pub value: u16,
pub changed: bool,
}
impl fmt::Display for AxisData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Value: {} Changed?: {}", self.value, self.changed)
}
}
impl<I2C, E> Bma222e<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
{
pub fn new(dev: I2C) -> Self {
Self { device: dev }
}
fn write(&mut self, register: u8, data: &[u8]) -> Result<(), E> {
let mut input = [0u8; 16]; assert!(
data.len() < 16 - 1,
"write() can only take buffers up to 15 bytes ☹️"
);
input[1..=data.len()].copy_from_slice(data);
input[0] = register;
self.device.write(ADDRESS, &input)?;
Ok(())
}
fn read(&mut self, register: u8, data: &mut [u8]) -> Result<(), E> {
self.device.write_read(ADDRESS, &[register], data)?;
Ok(())
}
fn single_read(&mut self, register: u8) -> Result<u8, E> {
let mut out = [0u8; 1];
self.read(register, &mut out)?;
Ok(out[0])
}
pub fn reset(&mut self) -> Result<(), E> {
self.write(ADDRESS, &[REG_RESET, 0xB6])?;
Ok(())
}
pub fn temperature(&mut self) -> Result<u8, E> {
let value = self.single_read(REG_TEMPERATURE)?;
Ok(value.wrapping_add(23))
}
pub fn who_am_i(&mut self) -> Result<u8, E> {
Ok(self.single_read(REG_CHIPID)?)
}
pub fn fifo_set_mode(&mut self, mode: FIFOConfig) -> Result<(), E> {
let value = (mode as u8) << 6;
self.write(REG_FIFO_CONFIG, &[value])?;
Ok(())
}
pub fn fifo_size(&mut self) -> Result<u8, E> {
let value = self.single_read(REG_FIFO_STATUS)?;
Ok(value & 0b0111_1111)
}
pub fn fifo_overflow(&mut self) -> Result<bool, E> {
let value = self.single_read(REG_FIFO_STATUS)?;
Ok(value & 0b1000_0000 != 0)
}
pub fn fifo_get(&mut self, data: &mut [AxisData]) -> Result<(), E> {
let mut out = [0u8; 6];
let mut index: usize = 0;
for item in data {
self.read(REG_FIFO_DATA, &mut out)?;
item.changed = out[index] & 0x01 != 0;
item.value = u16::from(out[index + 1]);
if index == 3 {
index = 0;
} else {
index += 1;
}
}
Ok(())
}
pub fn element_get(&mut self, register: u8) -> Result<AxisData, E> {
let mut out = [0u8; 2];
self.read(register, &mut out)?;
let item = AxisData {
value: u16::from(out[1]),
changed: out[0] & 0x01 != 0,
};
Ok(item)
}
pub fn axis_x(&mut self) -> Result<AxisData, E> {
Ok(self.element_get(REG_XAXIS)?)
}
pub fn axis_y(&mut self) -> Result<AxisData, E> {
Ok(self.element_get(REG_YAXIS)?)
}
pub fn axis_z(&mut self) -> Result<AxisData, E> {
Ok(self.element_get(REG_ZAXIS)?)
}
pub fn eeprom_writes_remaining(&mut self) -> Result<u8, E> {
let value = self.single_read(REG_EEPROM_CONTROL)?;
let value = (value | 0b1111_0000) >> 4;
Ok(value)
}
pub fn eeprom_data(&mut self) -> Result<[u8; EEPROM_LENGTH], E> {
let mut out = [0u8; EEPROM_LENGTH];
self.read(REG_EEPROM_START, &mut out)?;
Ok(out)
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(1 + 1, 2);
}
}