extern crate embedded_hal_mock as hal; extern crate opt300x; use hal::eh1::i2c::{Mock as I2cMock, Transaction as I2cTrans}; use opt300x::{ ComparisonMode, Error, FaultCount, IntegrationTime, InterruptPinPolarity, LuxRange, Opt300x, SlaveAddr, Status, }; mod common; use self::common::{destroy, new_opt3001, BitFlags as BF, Register as Reg, CFG_DEFAULT, DEV_ADDR}; macro_rules! create_destroy_test { ($name:ident, $method:ident) => { #[test] fn $name() { let sensor = Opt300x::$method(I2cMock::new(&[]), SlaveAddr::default()); destroy(sensor); } }; } create_destroy_test!(create_and_destroy_opt3001, new_opt3001); create_destroy_test!(create_and_destroy_opt3002, new_opt3002); create_destroy_test!(create_and_destroy_opt3004, new_opt3004); create_destroy_test!(create_and_destroy_opt3006, new_opt3006); #[test] fn create_and_destroy_opt3007() { let sensor = Opt300x::new_opt3007(I2cMock::new(&[])); destroy(sensor); } macro_rules! get_test { ($name:ident, $method:ident, $register:ident, $value:expr, $expected:expr) => { #[test] fn $name() { let transactions = [I2cTrans::write_read( DEV_ADDR, vec![Reg::$register], vec![($value >> 8) as u8, ($value & 0xFF) as u8], )]; let mut sensor = new_opt3001(&transactions); let result = sensor.$method().unwrap(); assert_eq!($expected, result); destroy(sensor); } }; } get_test!(can_read_dev_id, get_device_id, DEVICE_ID, 0xABCD, 0xABCD); get_test!( can_read_manuf_id, get_manufacturer_id, MANUFACTURER_ID, 0xABCD, 0xABCD ); macro_rules! read_lux_test { ($name:ident, $value:expr, $expected:expr) => { #[test] fn $name() { let transactions = [ I2cTrans::write( DEV_ADDR, vec![ Reg::CONFIG, ((CFG_DEFAULT | BF::MODE0 | BF::MODE1) >> 8) as u8, CFG_DEFAULT as u8, ], ), I2cTrans::write_read( DEV_ADDR, vec![Reg::RESULT], vec![($value >> 8) as u8, ($value & 0xFF) as u8], ), ]; let sensor = new_opt3001(&transactions); let mut sensor = sensor.into_continuous().ok().unwrap(); let result = sensor.read_lux().unwrap(); assert!(result > $expected - 0.5); assert!(result < $expected + 0.5); destroy(sensor); } }; } read_lux_test!(lux_0_01, 0x01, 0.01); read_lux_test!(lux_40, 0xFFF, 40.95); read_lux_test!(lux_88, 0x3456, 88.80); read_lux_test!(lux_2818, 0x789A, 2818.56); read_lux_test!(lux_5242_1, 0x8800, 5242.88); read_lux_test!(lux_5242_2, 0x9400, 5242.88); read_lux_test!(lux_5242_3, 0xA200, 5242.88); read_lux_test!(lux_5242_4, 0xB100, 5242.88); read_lux_test!(lux_20, 0xB001, 20.48); read_lux_test!(lux_83k, 0xBFFF, 83_865.6); macro_rules! read_raw_test { ($name:ident, $value:expr, $expected:expr) => { #[test] fn $name() { let transactions = [ I2cTrans::write( DEV_ADDR, vec![ Reg::CONFIG, ((CFG_DEFAULT | BF::MODE0 | BF::MODE1) >> 8) as u8, CFG_DEFAULT as u8, ], ), I2cTrans::write_read( DEV_ADDR, vec![Reg::RESULT], vec![($value >> 8) as u8, ($value & 0xFF) as u8], ), ]; let sensor = new_opt3001(&transactions); let mut sensor = sensor.into_continuous().ok().unwrap(); let result = sensor.read_raw().unwrap(); assert_eq!($expected, result); destroy(sensor); } }; } read_raw_test!(raw_0_01, 0x01, (0, 0x01)); read_raw_test!(raw_40, 0xFFF, (0, 0xFFF)); read_raw_test!(raw_88, 0x3456, (0x3, 0x456)); read_raw_test!(raw_2818, 0x789A, (0x7, 0x89A)); read_raw_test!(raw_5242_1, 0x8800, (0x8, 0x800)); read_raw_test!(raw_5242_2, 0x9400, (0x9, 0x400)); read_raw_test!(raw_5242_3, 0xA200, (0xA, 0x200)); read_raw_test!(raw_5242_4, 0xB100, (0xB, 0x100)); read_raw_test!(raw_20, 0xB001, (0xB, 0x01)); read_raw_test!(raw_83k, 0xBFFF, (0xB, 0xFFF)); get_test!( status_overflow, read_status, CONFIG, BF::OVF, Status { has_overflown: true, conversion_ready: false, was_too_high: false, was_too_low: false, } ); get_test!( status_all_false, read_status, CONFIG, 0, Status { has_overflown: false, conversion_ready: false, was_too_high: false, was_too_low: false, } ); get_test!( status_conversion_ready, read_status, CONFIG, BF::CRF, Status { has_overflown: false, conversion_ready: true, was_too_high: false, was_too_low: false, } ); get_test!( status_too_high, read_status, CONFIG, BF::FH, Status { has_overflown: false, conversion_ready: false, was_too_high: true, was_too_low: false, } ); get_test!( status_too_low, read_status, CONFIG, BF::FL, Status { has_overflown: false, conversion_ready: false, was_too_high: false, was_too_low: true, } ); get_test!( status_all_true, read_status, CONFIG, BF::OVF | BF::CRF | BF::FH | BF::FL, Status { has_overflown: true, conversion_ready: true, was_too_high: true, was_too_low: true, } ); macro_rules! set_test { ($name:ident, $method:ident, $register:ident, $value:expr $(, $arg:expr)*) => { #[test] fn $name() { let transactions = [I2cTrans::write( DEV_ADDR, vec![Reg::$register, ($value >> 8) as u8, $value as u8], )]; let mut sensor = new_opt3001(&transactions); sensor.$method($($arg),*).unwrap(); destroy(sensor); } }; } macro_rules! cfg_test { ($name:ident, $method:ident, $value:expr $(, $arg:expr)*) => { set_test!($name, $method, CONFIG, $value $(, $arg)*); }; } cfg_test!(faultc1, set_fault_count, CFG_DEFAULT, FaultCount::One); cfg_test!(faultc2, set_fault_count, CFG_DEFAULT | 1, FaultCount::Two); cfg_test!(faultc4, set_fault_count, CFG_DEFAULT | 2, FaultCount::Four); cfg_test!(faultc8, set_fault_count, CFG_DEFAULT | 3, FaultCount::Eight); cfg_test!( int_pin_polarity_low, set_interrupt_pin_polarity, CFG_DEFAULT, InterruptPinPolarity::Low ); cfg_test!( int_pin_polarity_high, set_interrupt_pin_polarity, CFG_DEFAULT | BF::POL, InterruptPinPolarity::High ); cfg_test!( comp_mode_latched_window, set_comparison_mode, CFG_DEFAULT, ComparisonMode::LatchedWindow ); cfg_test!( comp_mode_transparent, set_comparison_mode, CFG_DEFAULT & !BF::L, ComparisonMode::TransparentHysteresis ); #[test] fn can_change_mode() { let transactions = [ I2cTrans::write( DEV_ADDR, vec![ Reg::CONFIG, ((CFG_DEFAULT | BF::MODE0 | BF::MODE1) >> 8) as u8, CFG_DEFAULT as u8, ], ), I2cTrans::write( DEV_ADDR, vec![Reg::CONFIG, (CFG_DEFAULT >> 8) as u8, CFG_DEFAULT as u8], ), I2cTrans::write( DEV_ADDR, vec![ Reg::CONFIG, ((CFG_DEFAULT | BF::MODE0 | BF::MODE1) >> 8) as u8, CFG_DEFAULT as u8, ], ), ]; let sensor = new_opt3001(&transactions); let sensor = sensor.into_continuous().ok().unwrap(); let sensor = sensor.into_one_shot().ok().unwrap(); let sensor = sensor.into_continuous().ok().unwrap(); destroy(sensor); } set_invalid_test!( too_high_lux_range, new_opt3001, destroy, set_lux_range, LuxRange::Manual(0b1100) ); cfg_test!( set_lux_range_auto, set_lux_range, CFG_DEFAULT, LuxRange::Auto ); cfg_test!( set_lux_range_manual_0, set_lux_range, CFG_DEFAULT & 0x0FFF, LuxRange::Manual(0) ); cfg_test!( set_lux_range_manual_max, set_lux_range, CFG_DEFAULT & 0x0FFF | 0b1011 << 12, LuxRange::Manual(0b1011) ); cfg_test!( set_integration_time_100, set_integration_time, CFG_DEFAULT & !BF::CT, IntegrationTime::Ms100 ); cfg_test!( set_integration_time_800, set_integration_time, CFG_DEFAULT | BF::CT, IntegrationTime::Ms800 ); cfg_test!( enable_exponent_masking, enable_exponent_masking, CFG_DEFAULT | BF::ME ); cfg_test!( disable_exponent_masking, disable_exponent_masking, CFG_DEFAULT & !BF::ME ); macro_rules! invalid_test { ($name:ident, $method:ident $(, $arg:expr)*) => { #[test] fn $name() { let mut sensor = new_opt3001(&[]); if let Err(Error::InvalidInputData) = sensor.$method($($arg),*) { } else { panic!("Should have returned error"); } destroy(sensor); } }; } invalid_test!(low_limit_exp_too_big, set_low_limit_raw, 0b1100, 0); invalid_test!(low_limit_mant_too_big, set_low_limit_raw, 0, 0x1000); set_test!( set_low_limit, set_low_limit_raw, LOW_LIMIT, 0xBFFF_u16, 0xB, 0xFFF ); invalid_test!(high_limit_exp_too_big, set_high_limit_raw, 0b1100, 0); invalid_test!(high_limit_mant_too_big, set_high_limit_raw, 0, 0x1000); set_test!( set_high_limit, set_high_limit_raw, HIGH_LIMIT, 0xBFFF_u16, 0xB, 0xFFF ); set_test!( enable_end_of_conv, enable_end_of_conversion_mode, LOW_LIMIT, 0b11 << 14 ); set_test!( disable_end_of_conv, disable_end_of_conversion_mode, LOW_LIMIT, 0 ); #[test] fn configured_low_limit_is_restored_after_disabling_end_of_conv() { let low_limit = 0b1010_1010_1010_1010; let transactions = [ I2cTrans::write( DEV_ADDR, vec![Reg::LOW_LIMIT, (low_limit >> 8) as u8, low_limit as u8], ), I2cTrans::write( DEV_ADDR, vec![ Reg::LOW_LIMIT, (low_limit >> 8) as u8 | 0b11 << 6, low_limit as u8, ], ), I2cTrans::write( DEV_ADDR, vec![Reg::LOW_LIMIT, (low_limit >> 8) as u8, low_limit as u8], ), ]; let mut sensor = new_opt3001(&transactions); sensor .set_low_limit_raw((low_limit >> 12) as u8, low_limit & 0xFFF) .unwrap(); sensor.enable_end_of_conversion_mode().unwrap(); sensor.disable_end_of_conversion_mode().unwrap(); destroy(sensor); }