use bilge::prelude::*;
use bytemuck::{AnyBitPattern, NoUninit};
use defmt::Format;
#[bitsize(8)]
#[derive(DebugBits, FromBits, PartialEq)]
pub struct FifoHeader {
odr_changed_gyro: u1, odr_changed_accel: u1, has_timestamp_fsync: u2, has_20bit: u1, has_gyro: u1, has_accel: u1, header_msg: u1, }
impl defmt::Format for FifoHeader {
fn format(&self, f: defmt::Formatter) {
defmt::write!(f, "FifoHeader {{ header_msg: {}, has_accel: {}, has_gyro: {}, has_20bit: {}, has_timestamp_fsync: {}, odr_changed_accel: {}, odr_changed_gyro: {} }}",
self.header_msg().value(),
self.has_accel().value(),
self.has_gyro().value(),
self.has_20bit().value(),
self.has_timestamp_fsync().value(),
self.odr_changed_accel().value(),
self.odr_changed_gyro().value(),
);
}
}
#[derive(Debug, Clone, Copy, Format, PartialEq, NoUninit, AnyBitPattern)]
#[repr(C)]
pub struct FifoPacket4 {
pub fifo_header: u8,
pub accel_data_x1: u8, pub accel_data_x0: u8, pub accel_data_y1: u8, pub accel_data_y0: u8, pub accel_data_z1: u8, pub accel_data_z0: u8, pub gyro_data_x1: u8, pub gyro_data_x0: u8, pub gyro_data_y1: u8, pub gyro_data_y0: u8, pub gyro_data_z1: u8, pub gyro_data_z0: u8, pub temp_data1: u8, pub temp_data0: u8, pub timestamp_h: u8, pub timestamp_l: u8, pub ext_accel_x_gyro_x: u8, pub ext_accel_y_gyro_y: u8, pub ext_accel_z_gyro_z: u8, }
impl FifoPacket4 {
pub fn fifo_header(&self) -> FifoHeader {
FifoHeader::from(self.fifo_header)
}
#[inline]
fn convert_parts_to_20bit(&self, high_8: u8, low_8: u8, ext_low_4: u8) -> i32 {
let high_12 = (high_8 as u32) << 12;
let low_12 = (low_8 as u32) << 4;
let ext_4 = (ext_low_4 & 0xF) as u32;
let value = high_12 | low_12 | ext_4;
let sign_extended = if value & 0x80000 != 0 {
value | 0xFFF00000
} else {
value
};
sign_extended as i32
}
pub fn accel_data_x(&self) -> i32 {
let ext_accel_x = (self.ext_accel_x_gyro_x & 0xF0) >> 4;
self.convert_parts_to_20bit(self.accel_data_x1, self.accel_data_x0, ext_accel_x)
}
pub fn accel_data_y(&self) -> i32 {
let ext_accel_y = (self.ext_accel_y_gyro_y & 0xF0) >> 4;
self.convert_parts_to_20bit(self.accel_data_y1, self.accel_data_y0, ext_accel_y)
}
pub fn accel_data_z(&self) -> i32 {
let ext_accel_z = (self.ext_accel_z_gyro_z & 0xF0) >> 4;
self.convert_parts_to_20bit(self.accel_data_z1, self.accel_data_z0, ext_accel_z)
}
pub fn gyro_data_x(&self) -> i32 {
let ext_gyro_x = self.ext_accel_x_gyro_x & 0x0F;
self.convert_parts_to_20bit(self.gyro_data_x1, self.gyro_data_x0, ext_gyro_x)
}
pub fn gyro_data_y(&self) -> i32 {
let ext_gyro_y = self.ext_accel_y_gyro_y & 0x0F;
self.convert_parts_to_20bit(self.gyro_data_y1, self.gyro_data_y0, ext_gyro_y)
}
pub fn gyro_data_z(&self) -> i32 {
let ext_gyro_z = self.ext_accel_z_gyro_z & 0x0F;
self.convert_parts_to_20bit(self.gyro_data_z1, self.gyro_data_z0, ext_gyro_z)
}
pub fn temperature_raw(&self) -> u16 {
((self.temp_data1 as u16) << 8) | self.temp_data0 as u16
}
pub fn timestamp(&self) -> u16 {
((self.timestamp_h as u16) << 8) | self.timestamp_l as u16
}
}
const _SIZE_CHECK: usize = (core::mem::size_of::<FifoPacket4>() == 20) as usize - 1;