#![forbid(unsafe_code)]
#![cfg_attr(not(test), no_std)]
mod register;
use embedded_hal as hal;
use crate::register::Register;
use core::fmt::Debug;
use hal::blocking::i2c::{Write, WriteRead};
#[derive(Clone, Copy)]
pub enum I2CAddressSwitchState {
OnOnOnOn = 0xB0,
OffOnOnOn = 0xB2,
OnOffOnOn = 0xB4,
OffOffOnOn = 0xB6,
OnOnOffOn = 0xB8,
OffOnOffOn = 0xBA,
OnOffOffOn = 0xBC,
OffOffOffOn = 0xBE,
}
impl I2CAddressSwitchState {
fn bits(self) -> u8 {
self as u8
}
}
#[derive(Clone, Copy)]
pub enum OperatingMode {
Mode0,
Mode1,
}
impl OperatingMode {
pub fn bits(self) -> u8 {
self as u8
}
pub fn is_turn_mode(&self) -> bool {
match self {
OperatingMode::Mode0 | OperatingMode::Mode1 => false,
_ => true,
}
}
}
pub struct Md22<I2C> {
i2c: I2C,
mode: u8,
address: u8,
}
impl<I2C, E> Md22<I2C>
where
I2C: WriteRead<Error = E> + Write<Error = E>,
E: Debug,
{
pub fn new(i2c: I2C, mode: OperatingMode, address: I2CAddressSwitchState) -> Result<Self, E> {
let mut md22 = Md22 {
i2c: i2c,
mode: mode.bits(),
address: address.bits()
};
md22.set_mode(mode)?;
md22.set_acceleration(0)?;
md22.set_speed(0)?;
md22.set_turn(0)?;
Ok(md22)
}
pub fn set_mode(&mut self, mode: OperatingMode) -> Result<(), E> {
let bytes = [Register::Mode.addr(), mode as u8];
self.i2c.write(self.address, &bytes)?;
Ok(())
}
pub fn set_speed(&mut self, speed: u8) -> Result<(), E> {
let bytes = [Register::Speed.addr(), speed];
self.i2c.write(self.address, &bytes)?;
Ok(())
}
pub fn set_turn(&mut self, turn: u8) -> Result<(), E> {
let bytes = [Register::Turn.addr(), turn];
self.i2c.write(self.address, &bytes)?;
Ok(())
}
pub fn set_acceleration(&mut self, acceleration: u8) -> Result<(), E> {
let bytes = [Register::Acceleration.addr(), acceleration];
self.i2c.write(self.address, &bytes)?;
Ok(())
}
pub fn get_software_revision(&mut self) -> Result<u8, E> {
let bytes = [Register::SoftwareRevision.addr()];
let mut buffer: [u8;1] = [0;1];
self.i2c.write_read(self.address, &bytes, &mut buffer)?;
Ok(buffer[0])
}
}
#[cfg(test)]
mod tests {
use crate::*;
use embedded_hal_mock as hal;
#[test]
fn get_software_revision() {
let address = I2CAddressSwitchState::OnOnOnOn;
let expectation = [
hal::i2c::Transaction::write(address.bits(), vec![Register::Mode.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Acceleration.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Speed.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Turn.addr(), 0]),
hal::i2c::Transaction::write_read(address.bits(), vec![Register::SoftwareRevision.addr()], vec![255]),
];
let i2c = hal::i2c::Mock::new(&expectation);
let mut md22 = Md22::new(i2c, OperatingMode::Mode0, address).unwrap();
assert_eq!(255, md22.get_software_revision().unwrap());
}
#[test]
fn set_mode() {
let address = I2CAddressSwitchState::OnOnOnOn;
let expectation = [
hal::i2c::Transaction::write(address.bits(), vec![Register::Mode.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Acceleration.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Speed.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Turn.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Mode.addr(), OperatingMode::Mode1.bits()]),
];
let i2c = hal::i2c::Mock::new(&expectation);
let mut md22 = Md22::new(i2c, OperatingMode::Mode0, address).unwrap();
md22.set_mode(OperatingMode::Mode1).unwrap();
}
#[test]
fn set_acceleration() {
let address = I2CAddressSwitchState::OnOnOnOn;
let expectation = [
hal::i2c::Transaction::write(address.bits(), vec![Register::Mode.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Acceleration.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Speed.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Turn.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Acceleration.addr(), 255]),
];
let i2c = hal::i2c::Mock::new(&expectation);
let mut md22 = Md22::new(i2c, OperatingMode::Mode0, address).unwrap();
md22.set_acceleration(255).unwrap();
}
#[test]
fn set_speed() {
let address = I2CAddressSwitchState::OnOnOnOn;
let expectation = [
hal::i2c::Transaction::write(address.bits(), vec![Register::Mode.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Acceleration.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Speed.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Turn.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Speed.addr(), 255]),
];
let i2c = hal::i2c::Mock::new(&expectation);
let mut md22 = Md22::new(i2c, OperatingMode::Mode0, address).unwrap();
md22.set_speed(255).unwrap();
}
#[test]
fn set_turn() {
let address = I2CAddressSwitchState::OnOnOnOn;
let expectation = [
hal::i2c::Transaction::write(address.bits(), vec![Register::Mode.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Acceleration.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Speed.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Turn.addr(), 0]),
hal::i2c::Transaction::write(address.bits(), vec![Register::Turn.addr(), 255]),
];
let i2c = hal::i2c::Mock::new(&expectation);
let mut md22 = Md22::new(i2c, OperatingMode::Mode0, address).unwrap();
md22.set_turn(255).unwrap();
}
}