#![deny(warnings)]
#![no_std]
extern crate cast;
extern crate embedded_hal as hal;
use core::mem;
use cast::u16;
use hal::blocking::i2c::{Write, WriteRead};
pub const ADDRESS: u8 = 0x0E;
#[allow(dead_code)]
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Register {
DR_STATUS = 0x00, OUT_X_MSB = 0x01, OUT_X_LSB = 0x02, OUT_Y_MSB = 0x03, OUT_Y_LSB = 0x04, OUT_Z_MSB = 0x05, OUT_Z_LSB = 0x06, WHO_AM_I = 0x07, SYSMOD = 0x08, OFF_X_MSB = 0x09, OFF_X_LSB = 0x0A, OFF_Y_MSB = 0x0B, OFF_Y_LSB = 0x0C, OFF_Z_MSB = 0x0D, OFF_Z_LSB = 0x0E, DIE_TEMP = 0x0F, CTRL_REG1 = 0x10, CTRL_REG2 = 0x11, }
impl Register {
pub fn addr(&self) -> u8 {
*self as u8
}
}
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum DataRate {
HZ80 = 0b0000_0000, HZ40 = 0b0010_0000, HZ20 = 0b0100_0000, HZ10 = 0b0110_0000, HZ5 = 0b1000_0000, HZ2_5 = 0b1010_0000, HZ1_25 = 0b1100_0000, HZ0_63 = 0b1110_0000, }
impl DataRate {
pub fn bits(&self) -> u8 {
*self as u8
}
}
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum Oversampling {
OV16 = 0b0000_0000, OV32 = 0b0000_1000, OV64 = 0b0001_0000, OV128 = 0b0001_1000, }
impl Oversampling {
pub fn bits(&self) -> u8 {
*self as u8
}
}
pub struct Mag3110<I2C> {
i2c: I2C,
}
impl<I2C, E> Mag3110<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
{
pub fn new(i2c: I2C) -> Result<Self, E> {
let mut mag3110 = Self { i2c };
mag3110.set_sampling_mode(DataRate::HZ80, Oversampling::OV16)?;
Ok(mag3110)
}
pub fn set_sampling_mode(&mut self, dr: DataRate, ov: Oversampling) -> Result<(), E> {
let _ = self.stop_sampling()?;
self.write_register(Register::CTRL_REG1, dr.bits() | ov.bits() | 1)?;
Ok(())
}
pub fn mag(&mut self) -> Result<(i16, i16, i16), E> {
let mut buffer: [u8; 6] = unsafe { mem::uninitialized() };
self.i2c
.write_read(ADDRESS, &[Register::OUT_X_MSB.addr()], &mut buffer)?;
Ok((
(u16(buffer[1]) | (u16(buffer[0]) << 8)) as i16,
(u16(buffer[3]) | (u16(buffer[2]) << 8)) as i16,
(u16(buffer[5]) | (u16(buffer[4]) << 8)) as i16,
))
}
pub fn temp(&mut self) -> Result<i8, E> {
let mut buffer: [u8; 1] = unsafe { mem::uninitialized() };
self.i2c
.write_read(ADDRESS, &[Register::DIE_TEMP.addr()], &mut buffer)?;
Ok(buffer[0] as i8)
}
pub fn stop_sampling(&mut self) -> Result<(), E> {
loop {
self.write_register(Register::CTRL_REG1, 0)?;
let mut buffer: [u8; 1] = unsafe { mem::uninitialized() };
self.i2c
.write_read(ADDRESS, &[Register::SYSMOD.addr()], &mut buffer)?;
if buffer[0] == 0 {
break Ok(());
}
}
}
fn write_register(&mut self, reg: Register, byte: u8) -> Result<(), E> {
self.i2c.write(ADDRESS, &[reg.addr(), byte])
}
}