as5600 0.8.0

Platform-independent Rust driver for AS5600 digital magnetic potentiometer
Documentation
use crate::{
    configuration::{
        Configuration, FastFilterThreshold, Hysteresis, OutputStage, PowerMode, PwmFreq,
        SlowFilterMode, WatchdogState,
    },
    error::Error,
    As5600,
};
use embedded_hal_mock::eh1::{
    delay::NoopDelay,
    i2c::{Mock, Transaction},
};

#[test]
fn set_zero_position() {
    let i2c = Mock::new(&[
        Transaction::write(0x36, vec![0x01, 0x0A, 0xAF]),
        Transaction::write(0x36, vec![0x01, 0x01, 0x10]),
        Transaction::write(0x36, vec![0x01, 0x0A, 0xCA]),
        Transaction::write(0x36, vec![0x01, 0x01, 0x0B]),
    ]);
    let mut as5600 = As5600::new(i2c);
    for angle in [0x1AAF, 0x0110, 0x0ACA, 0x010B] {
        as5600.set_zero_position(angle).unwrap();
    }
    as5600.release().done();
}

#[test]
fn set_maximum_position() {
    let i2c = Mock::new(&[
        Transaction::write(0x36, vec![0x03, 0x0F, 0xAF]),
        Transaction::write(0x36, vec![0x03, 0x00, 0x10]),
        Transaction::write(0x36, vec![0x03, 0x0F, 0xAF]),
        Transaction::write(0x36, vec![0x03, 0x01, 0x00]),
    ]);
    let mut as5600 = As5600::new(i2c);
    for angle in [0xAFAF, 0x2010, 0x1FAF, 0x1100] {
        as5600.set_maximum_position(angle).unwrap();
    }
    as5600.release().done();
}

#[test]
fn set_maximum_angle() {
    let i2c = Mock::new(&[
        Transaction::write(0x36, vec![0x05, 0x0F, 0xFA]),
        Transaction::write(0x36, vec![0x05, 0x00, 0x01]),
        Transaction::write(0x36, vec![0x05, 0x0F, 0xFA]),
        Transaction::write(0x36, vec![0x05, 0x00, 0x00]),
    ]);
    let mut as5600 = As5600::new(i2c);
    for angle in [0x0FFA, 0x0001, 0xAFFA, 0x1000] {
        as5600.set_maximum_angle(angle).unwrap();
    }
    as5600.release().done();
}

#[test]
fn set_config() {
    let config = Configuration {
        power_mode: PowerMode::Lpm1,
        hysteresis: Hysteresis::Lsb2,
        output_stage: OutputStage::DigitalPwm,
        pwm_frequency: PwmFreq::PwmF2,
        slow_filter: SlowFilterMode::X2,
        fast_filter_threshold: FastFilterThreshold::Lsb21,
        watchdog_state: WatchdogState::On,
    };
    let config_bytes: [u8; 2] = u16::from(config).to_be_bytes();
    let top_most_set = config_bytes[0] | 0b1000_0000;

    let i2c = Mock::new(&[
        Transaction::write_read(0x36, vec![0x07], vec![top_most_set, config_bytes[1]]),
        Transaction::write(0x36, vec![0x07, top_most_set, config_bytes[1]]),
    ]);
    let mut as5600 = As5600::new(i2c);
    as5600.set_config(config).unwrap();
    as5600.release().done();
}

#[test]
fn burn_angle_succeeds() {
    let i2c = Mock::new(&[
        Transaction::write_read(0x36, vec![0x00], vec![0b0000_0001]),
        Transaction::write_read(0x36, vec![0x0b], vec![0x20]),
        Transaction::write(0x36, vec![0xFF, 0x80]),
    ]);
    let mut delay = NoopDelay;
    let mut as5600 = As5600::new(i2c);
    as5600.persist_position_settings(&mut delay).unwrap();
    as5600.release().done();
}

#[test]
fn burn_angle_fails_due_to_zmco() {
    let i2c = Mock::new(&[Transaction::write_read(0x36, vec![0x00], vec![0b0000_0011])]);
    let mut delay = NoopDelay;
    let mut as5600 = As5600::new(i2c);
    assert_eq!(
        as5600.persist_position_settings(&mut delay).unwrap_err(),
        Error::MaximumPositionPersistsReached
    );
    as5600.release().done();
}

#[test]
fn burn_angle_fails_due_to_magnet_detection() {
    let i2c = Mock::new(&[
        Transaction::write_read(0x36, vec![0x00], vec![0b0000_0001]),
        Transaction::write_read(0x36, vec![0x0b], vec![0x10]),
    ]);
    let mut delay = NoopDelay;
    let mut as5600 = As5600::new(i2c);
    assert_eq!(
        as5600.persist_position_settings(&mut delay).unwrap_err(),
        Error::MagnetRequired
    );
    as5600.release().done();
}

#[test]
fn burn_settings_succeeds() {
    let i2c = Mock::new(&[
        Transaction::write_read(0x36, vec![0x00], vec![0b0000_0000]),
        Transaction::write(0x36, vec![0xFF, 0x40]),
    ]);
    let mut delay = NoopDelay;
    let mut as5600 = As5600::new(i2c);
    as5600
        .persist_maximum_angle_and_config_settings(&mut delay)
        .unwrap();
    as5600.release().done();
}

#[test]
fn burn_settings_fails_when_zmco_is_not_zero() {
    let i2c = Mock::new(&[Transaction::write_read(0x36, vec![0x00], vec![0b0000_0001])]);
    let mut delay = NoopDelay;
    let mut as5600 = As5600::new(i2c);
    assert_eq!(
        as5600
            .persist_maximum_angle_and_config_settings(&mut delay)
            .unwrap_err(),
        Error::MangConfigPersistenceExhausted
    );
    as5600.release().done();
}