use std::time::Duration;
use bno08x_rs::{
interface::{
delay::delay_ms,
gpio::{GpiodIn, GpiodOut},
spidev::SpiDevice,
SpiInterface,
},
BNO08x, SENSOR_REPORTID_ACCELEROMETER, SENSOR_REPORTID_GYROSCOPE,
SENSOR_REPORTID_ROTATION_VECTOR,
};
pub struct Driver<'a> {
pub imu_driver: BNO08x<'a, SpiInterface<SpiDevice, GpiodIn, GpiodOut>>,
}
pub const ROTATION_VECTOR_UPDATE: Duration = Duration::from_millis(5);
pub const ACCELEROMETER_UPDATE: Duration = Duration::from_millis(20);
pub const GYROSCOPE_UPDATE: Duration = Duration::from_millis(20);
impl Driver<'_> {
pub fn new(spidevice: &str, hintn_pin: &str, reset_pin: &str) -> Self {
let imu_driver = match BNO08x::new_spi_from_symbol(spidevice, hintn_pin, reset_pin) {
Ok(imu_driver) => imu_driver,
Err(_) => panic!("Initializing IMU driver failed!"),
};
Self { imu_driver }
}
pub fn enable_reports(&mut self) -> Result<(), String> {
let reports = [
(
SENSOR_REPORTID_ROTATION_VECTOR,
ROTATION_VECTOR_UPDATE.as_millis() as u16,
),
(
SENSOR_REPORTID_ACCELEROMETER,
ACCELEROMETER_UPDATE.as_millis() as u16,
),
(
SENSOR_REPORTID_GYROSCOPE,
GYROSCOPE_UPDATE.as_millis() as u16,
),
];
let max_tries = 5;
for (r, t) in reports {
let mut i = 0;
while i < max_tries && !self.imu_driver.is_report_enabled(r) {
let _ = self.imu_driver.enable_report(r, t);
i += 1;
}
if !self.imu_driver.is_report_enabled(r) {
return Err(format!("Could not enable report {}", r));
}
delay_ms(100);
}
Ok(())
}
pub fn configure_frs(&mut self) -> Result<(), String> {
let max_tries = 5;
let report_id = SENSOR_REPORTID_ACCELEROMETER;
let mut i = 0;
while i < max_tries && !self.imu_driver.is_report_enabled(report_id) {
let _ = self.imu_driver.enable_report(report_id, 100);
i += 1;
}
if !self.imu_driver.is_report_enabled(report_id) {
return Err(format!(
"Did not enable report {} for communication",
report_id
));
}
delay_ms(1000);
let mut last_err = "Success".to_string();
for _ in 0..max_tries {
match self
.imu_driver
.set_sensor_orientation(-1.0, 0.0, 0.0, 1.0, 2000)
{
Ok(v) if v => return Ok(()),
Ok(_) => last_err = "FRS records write failed".to_string(),
Err(e) => last_err = format!("{:?}", e),
};
}
Err(format!(
"Did not update sensor orientation FRS records after {} tries. The last error was {}",
max_tries, last_err,
))
}
}