diff --git a/example/src/main.rs b/example/src/main.rs index 2801cb11ff7a5c1ace2adf53e745a52e46cd7871..5be89cecb22fe0eb641e1e5c9bf6c99df3a456ac 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -8,11 +8,26 @@ main!(main); fn main() { writeln!(UART, "Hello from Rust\r").unwrap(); let bme = BME680::start(); + let a = BHI160::<Accelerometer>::start(); + let g = BHI160::<Gyroscope>::start(); + let o = BHI160::<Orientation>::start(); let display = Display::open(); let light = LightSensor::start(); for t in 0..Display::W { writeln!(UART, "BME: {:?}\r", bme.read()).unwrap(); + writeln!(UART, "A:\r").unwrap(); + for d in &a.read() { + writeln!(UART, " - {:?}\r", d).unwrap(); + } + writeln!(UART, "O:\r").unwrap(); + for d in &o.read() { + writeln!(UART, " - {:?}\r", d).unwrap(); + } + writeln!(UART, "G:\r").unwrap(); + for d in &g.read() { + writeln!(UART, " - {:?}\r", d).unwrap(); + } display.clear(Color::yellow()); display.print(160 - t, 10, b"Hello Rust\0", Color::white(), Color::black()); diff --git a/l0dable/src/bhi160.rs b/l0dable/src/bhi160.rs new file mode 100644 index 0000000000000000000000000000000000000000..6e16af2193d86048de8ee72dd5a5470bfda64fa9 --- /dev/null +++ b/l0dable/src/bhi160.rs @@ -0,0 +1,155 @@ +use core::mem::uninitialized; +use core::marker::PhantomData; +use super::bindings::*; + +use core::fmt::Write; + +pub trait SensorType { + /// sensor_type in C, sensor_id in Python + fn sensor_type() -> u32; + fn convert_single(value: i16) -> f32; +} + +pub struct Accelerometer; +impl SensorType for Accelerometer { + fn sensor_type() -> u32 { + 0 + } + fn convert_single(value: i16) -> f32 { + 2.0 * f32::from(value) / 32768.0 + } +} + +pub struct Gyroscope; +impl SensorType for Gyroscope { + fn sensor_type() -> u32 { + 3 + } + fn convert_single(value: i16) -> f32 { + 360.0 * f32::from(value) / 32768.0 + } +} + +pub struct Orientation; +impl SensorType for Orientation { + fn sensor_type() -> u32 { + 2 + } + fn convert_single(value: i16) -> f32 { + 360.0 * f32::from(value) / 32768.0 + } +} + + +pub struct Sensor<S: SensorType> { + stream_id: i32, + _kind: PhantomData<S>, +} + +impl<S: SensorType> Sensor<S> { + pub fn start() -> Self { + let mut cfg = bhi160_sensor_config { + sample_buffer_len: 200, + sample_rate: 4, + dynamic_range: 2, + _padding: [0u8; 8], + }; + let stream_id = unsafe { + epic_bhi160_enable_sensor(S::sensor_type(), &mut cfg) + }; + Sensor { + stream_id, + _kind: PhantomData, + } + } + + pub fn read(&self) -> SensorData<S> { + let mut buf: [bhi160_data_vector; 100] = unsafe { + uninitialized() + }; + let n = unsafe { + epic_stream_read(self.stream_id, buf.as_mut_ptr() as *mut _, buf.len()) + }; + if n < 0 { + panic!("epic_stream_read fail"); + } + let n = n as usize; + SensorData { + buf, n, + _kind: PhantomData, + } + } +} + +impl<S: SensorType> Drop for Sensor<S> { + fn drop(&mut self) { + unsafe { epic_bhi160_disable_sensor(S::sensor_type()); } + } +} + +const DATA_MAX: usize = 10; + +pub struct SensorData<S> { + buf: [bhi160_data_vector; DATA_MAX], + n: usize, + _kind: PhantomData<S>, +} + +impl<'a, S: SensorType> IntoIterator for &'a SensorData<S> { + type Item = SensorDataItem; + type IntoIter = SensorDataIter<'a, S>; + fn into_iter(self) -> Self::IntoIter { + SensorDataIter { + data: self, + pos: 0, + } + } +} + +pub struct SensorDataIter<'a, S> { + data: &'a SensorData<S>, + pos: usize, +} + +impl<'a, S: SensorType> Iterator for SensorDataIter<'a, S> { + type Item = SensorDataItem; + fn next(&mut self) -> Option<Self::Item> { + while self.pos < self.data.n { + let vec = &self.data.buf[self.pos]; + self.pos += 1; + if vec.data_type == DATA_TYPE_VECTOR { + let item = SensorDataItem { + x: S::convert_single(vec.x), + y: S::convert_single(vec.y), + z: S::convert_single(vec.z), + status: vec.status, + }; + return Some(item); + } else { + writeln!(crate::UART, "Sensor: skip type {}\r", vec.data_type).unwrap(); + } + } + None + } +} + +#[derive(Debug, Clone)] +pub struct SensorDataItem { + x: f32, + y: f32, + z: f32, + status: u8, +} + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct bhi160_data_vector { + /// This one is wrongly defined by buildgen + pub data_type: u8, + pub x: i16, + pub y: i16, + pub z: i16, + pub status: u8, +} + +const DATA_TYPE_VECTOR: u8 = 0; diff --git a/l0dable/src/lib.rs b/l0dable/src/lib.rs index 02da4f4fdb40d722677f7cc78d4fb17b06146ce5..e3960fdbedf7c0b89300226489f0022a53efa406 100644 --- a/l0dable/src/lib.rs +++ b/l0dable/src/lib.rs @@ -83,6 +83,8 @@ mod fmt_buffer; pub use fmt_buffer::FmtBuffer; mod bme680; pub use bme680::BME680; +mod bhi160; +pub use bhi160::{Sensor as BHI160, Accelerometer, Orientation, Gyroscope, SensorData as BHI160Data}; pub fn exit(ret: i32) -> ! { unsafe {