add lsm6ds3tr drivers
This commit is contained in:
parent
bf23b2d551
commit
f95f4b3f32
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1405,6 +1405,8 @@ dependencies = [
|
|||||||
"embassy-sync",
|
"embassy-sync",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embedded-alloc",
|
"embedded-alloc",
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
"embedded-hal-async",
|
||||||
"fixed",
|
"fixed",
|
||||||
"heapless",
|
"heapless",
|
||||||
"libm",
|
"libm",
|
||||||
|
@ -58,6 +58,7 @@ defmt = "0.3.0"
|
|||||||
defmt-rtt = "0.4.0"
|
defmt-rtt = "0.4.0"
|
||||||
embedded-storage = "0.3.0"
|
embedded-storage = "0.3.0"
|
||||||
embedded-hal = "1.0.0"
|
embedded-hal = "1.0.0"
|
||||||
|
embedded-hal-async = { version = "1.0.0" }
|
||||||
embedded-alloc = "0.6.0"
|
embedded-alloc = "0.6.0"
|
||||||
nrf-softdevice = { version = "0.1.0", features = [
|
nrf-softdevice = { version = "0.1.0", features = [
|
||||||
"defmt",
|
"defmt",
|
||||||
|
2
memory.x
2
memory.x
@ -1,5 +1,7 @@
|
|||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
|
/* https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsds_s140%2FSDS%2Fs1xx%2Fmem_usage%2Fmem_resource_reqs.html&cp=5_7_4_0_13_0_0 */
|
||||||
|
|
||||||
/* Need to leave space for the SoftDevice
|
/* Need to leave space for the SoftDevice
|
||||||
These values are confirmed working for S140 7.3.0
|
These values are confirmed working for S140 7.3.0
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ lsm6ds3tr.workspace = true
|
|||||||
defmt.workspace = true
|
defmt.workspace = true
|
||||||
defmt-rtt.workspace = true
|
defmt-rtt.workspace = true
|
||||||
embedded-alloc.workspace = true
|
embedded-alloc.workspace = true
|
||||||
|
embedded-hal.workspace = true
|
||||||
|
embedded-hal-async.workspace = true
|
||||||
nrf-softdevice.workspace = true
|
nrf-softdevice.workspace = true
|
||||||
nrf-softdevice-s140.workspace = true
|
nrf-softdevice-s140.workspace = true
|
||||||
embassy-nrf.workspace = true
|
embassy-nrf.workspace = true
|
||||||
|
8
tflite_demo/lsm6ds3tr/consts.rs
Normal file
8
tflite_demo/lsm6ds3tr/consts.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/// LSM6DS3TR-C's ID
|
||||||
|
pub const LSM6DS3TR_ID: u8 = 0x6A;
|
||||||
|
|
||||||
|
/// Temperature scale = 256 LSB/°C
|
||||||
|
pub const TEMP_SCALE: f32 = 256.0;
|
||||||
|
|
||||||
|
/// The output of the temperature sensor is 0 (typ.) at 25 °C
|
||||||
|
pub const TEMP_BIAS: f32 = 25.0;
|
28
tflite_demo/lsm6ds3tr/data.rs
Normal file
28
tflite_demo/lsm6ds3tr/data.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use core::fmt::{Display, Result};
|
||||||
|
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct XYZ<T> {
|
||||||
|
pub x: T,
|
||||||
|
pub y: T,
|
||||||
|
pub z: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Display for XYZ<T>
|
||||||
|
where
|
||||||
|
T: Display,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result {
|
||||||
|
write!(f, "X:{} Y:{} Z:{}", self.x, self.y, self.z)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
impl<T> defmt::Format for XYZ<T>
|
||||||
|
where
|
||||||
|
T: defmt::Format,
|
||||||
|
{
|
||||||
|
fn format(&self, f: defmt::Formatter) {
|
||||||
|
defmt::write!(f, "X:{} Y:{} Z:{}", self.x, self.y, self.z)
|
||||||
|
}
|
||||||
|
}
|
41
tflite_demo/lsm6ds3tr/interface/i2c.rs
Normal file
41
tflite_demo/lsm6ds3tr/interface/i2c.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use super::Interface;
|
||||||
|
use embedded_hal_async::i2c::I2c;
|
||||||
|
|
||||||
|
const I2C_ADDRESS: u8 = 0x6A;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum InterfaceE<CommE> {
|
||||||
|
Comm(CommE),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// I2C communication interface
|
||||||
|
pub struct I2cInterface<I2C> {
|
||||||
|
i2c: I2C,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I2C> I2cInterface<I2C> {
|
||||||
|
pub fn new(i2c: I2C) -> Self {
|
||||||
|
Self { i2c }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I2C, CommE> Interface for I2cInterface<I2C>
|
||||||
|
where
|
||||||
|
I2C: I2c<Error = CommE>,
|
||||||
|
{
|
||||||
|
type Error = InterfaceE<CommE>;
|
||||||
|
|
||||||
|
async fn write(&mut self, addr: u8, value: u8) -> Result<(), Self::Error> {
|
||||||
|
self.i2c
|
||||||
|
.write(I2C_ADDRESS, &[addr, value])
|
||||||
|
.await
|
||||||
|
.map_err(InterfaceE::Comm)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
|
self.i2c
|
||||||
|
.write_read(I2C_ADDRESS, &[addr], buffer)
|
||||||
|
.await
|
||||||
|
.map_err(InterfaceE::Comm)
|
||||||
|
}
|
||||||
|
}
|
10
tflite_demo/lsm6ds3tr/interface/mod.rs
Normal file
10
tflite_demo/lsm6ds3tr/interface/mod.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
pub mod i2c;
|
||||||
|
|
||||||
|
/// Communication interface
|
||||||
|
pub trait Interface {
|
||||||
|
type Error;
|
||||||
|
|
||||||
|
async fn write(&mut self, addr: u8, value: u8) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
async fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error>;
|
||||||
|
}
|
232
tflite_demo/lsm6ds3tr/mod.rs
Normal file
232
tflite_demo/lsm6ds3tr/mod.rs
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
mod consts;
|
||||||
|
mod data;
|
||||||
|
pub mod interface;
|
||||||
|
pub(crate) mod registers;
|
||||||
|
pub(crate) mod settings;
|
||||||
|
|
||||||
|
use consts::*;
|
||||||
|
pub use data::XYZ;
|
||||||
|
use interface::Interface;
|
||||||
|
pub use registers::{AccelSampleRate, AccelScale};
|
||||||
|
use registers::{
|
||||||
|
Ctrl3C, GyroSampleRate, GyroScale, RegisterAddress, RegisterBits, RegisterConfig,
|
||||||
|
RegisterValue, TapSrc, WakeUpSrc,
|
||||||
|
};
|
||||||
|
pub use settings::{
|
||||||
|
irq::{InterruptRoute, TapIrqSettings, TapRecognitionMode},
|
||||||
|
AccelSettings, GyroSettings, IrqSettings, LsmSettings,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Device driver
|
||||||
|
pub struct LSM6DS3TR<I>
|
||||||
|
where
|
||||||
|
I: Interface,
|
||||||
|
{
|
||||||
|
interface: I,
|
||||||
|
pub settings: LsmSettings,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I> LSM6DS3TR<I>
|
||||||
|
where
|
||||||
|
I: Interface,
|
||||||
|
{
|
||||||
|
/// Returns uninitialized device object with default settings
|
||||||
|
pub fn new(interface: I) -> Self {
|
||||||
|
Self {
|
||||||
|
interface,
|
||||||
|
settings: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns uninitialized device object with provided settings
|
||||||
|
pub fn with_settings(mut self, settings: LsmSettings) -> Self {
|
||||||
|
self.settings = settings;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes device with stored settings
|
||||||
|
pub async fn init(&mut self) -> Result<(), I::Error> {
|
||||||
|
self.init_accel().await?;
|
||||||
|
self.init_gyro().await?;
|
||||||
|
self.init_irqs().await?;
|
||||||
|
self.init_other().await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns if device is reachable
|
||||||
|
pub async fn is_reachable(&mut self) -> Result<bool, I::Error> {
|
||||||
|
Ok(self
|
||||||
|
.read_register(RegisterAddress::WHO_AM_I.address())
|
||||||
|
.await?
|
||||||
|
== LSM6DS3TR_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Performs a software reset
|
||||||
|
pub async fn software_reset(&mut self) -> Result<(), I::Error> {
|
||||||
|
let ctrl3_c = Ctrl3C {
|
||||||
|
software_reset: RegisterBits::new(1),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
self.write_register_config(ctrl3_c.config()).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes accelerometer with stored settings
|
||||||
|
pub async fn init_accel(&mut self) -> Result<(), I::Error> {
|
||||||
|
self.write_register_config(self.settings.accel.config())
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes gyroscope with stored settings
|
||||||
|
pub async fn init_gyro(&mut self) -> Result<(), I::Error> {
|
||||||
|
self.write_register_config(self.settings.gyro.config())
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes interrupts with stored settings
|
||||||
|
pub async fn init_irqs(&mut self) -> Result<(), I::Error> {
|
||||||
|
for config in self.settings.irq.configs() {
|
||||||
|
self.write_register_config(config).await?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes other options with stored settings
|
||||||
|
pub async fn init_other(&mut self) -> Result<(), I::Error> {
|
||||||
|
if self.settings.low_performance_mode {
|
||||||
|
self.write_register(RegisterAddress::CTRL6_C.address(), 1 << 4)
|
||||||
|
.await?; // TODO make it right like the others
|
||||||
|
self.write_register(RegisterAddress::CTRL7_G.address(), 1 << 7)
|
||||||
|
.await?; // TODO make it right like the others
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns accelerometer raw readings
|
||||||
|
pub async fn read_accel_raw(&mut self) -> Result<XYZ<i16>, I::Error> {
|
||||||
|
self.read_sensor_raw(RegisterAddress::OUTX_L_XL.address())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns accelerometer scaled readings \[g]
|
||||||
|
pub async fn read_accel(&mut self) -> Result<XYZ<f32>, I::Error> {
|
||||||
|
let xyz = self.read_accel_raw().await?;
|
||||||
|
let sensitivity = self.settings.accel.scale.sensitivity();
|
||||||
|
Ok(XYZ {
|
||||||
|
x: xyz.x as f32 * sensitivity,
|
||||||
|
y: xyz.y as f32 * sensitivity,
|
||||||
|
z: xyz.z as f32 * sensitivity,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns gyroscope raw readings
|
||||||
|
pub async fn read_gyro_raw(&mut self) -> Result<XYZ<i16>, I::Error> {
|
||||||
|
self.read_sensor_raw(RegisterAddress::OUTX_L_G.address())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns gyroscope scaled readings [°/s]
|
||||||
|
pub async fn read_gyro(&mut self) -> Result<XYZ<f32>, I::Error> {
|
||||||
|
let xyz = self.read_gyro_raw().await?;
|
||||||
|
let sensitivity = self.settings.gyro.scale.sensitivity();
|
||||||
|
Ok(XYZ {
|
||||||
|
x: xyz.x as f32 * sensitivity,
|
||||||
|
y: xyz.y as f32 * sensitivity,
|
||||||
|
z: xyz.z as f32 * sensitivity,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns temperature sensor raw reading
|
||||||
|
pub async fn read_temp_raw(&mut self) -> Result<i16, I::Error> {
|
||||||
|
let mut bytes = [0u8; 2];
|
||||||
|
self.interface
|
||||||
|
.read(RegisterAddress::OUT_TEMP_L.address(), &mut bytes)
|
||||||
|
.await?;
|
||||||
|
let temp: i16 = (bytes[1] as i16) << 8 | bytes[0] as i16;
|
||||||
|
Ok(temp)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns temperature sensor scaled reading [°C]
|
||||||
|
pub async fn read_temp(&mut self) -> Result<f32, I::Error> {
|
||||||
|
let temp = self.read_temp_raw().await?;
|
||||||
|
Ok(temp as f32 / TEMP_SCALE + TEMP_BIAS)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns last interrupt sources
|
||||||
|
/// TODO
|
||||||
|
// pub async fn read_interrupt_sources(&mut self) -> Result<Vec<IrqSource>, I::Error> {
|
||||||
|
// let mut wake_up_src = WakeUpSrc::default();
|
||||||
|
// let mut tap_src = TapSrc::default();
|
||||||
|
// // TODO add FUNC_SRC1 reading
|
||||||
|
// // TODO add FUNC_SRC2 reading
|
||||||
|
// wake_up_src = self.read_register(wake_up_src.address()).await?.into();
|
||||||
|
// tap_src = self.read_register(tap_src.address()).await?.into();
|
||||||
|
// let mut irq_sources = Vec::new();
|
||||||
|
// for source in wake_up_src.get_irq_sources() {
|
||||||
|
// irq_sources.push(source.clone());
|
||||||
|
// }
|
||||||
|
// for source in tap_src.get_irq_sources() {
|
||||||
|
// irq_sources.push(source.clone());
|
||||||
|
// }
|
||||||
|
// Ok(irq_sources)
|
||||||
|
// }
|
||||||
|
|
||||||
|
async fn read_sensor_raw(&mut self, addr: u8) -> Result<XYZ<i16>, I::Error> {
|
||||||
|
let mut bytes = [0u8; 6];
|
||||||
|
self.interface.read(addr, &mut bytes).await?;
|
||||||
|
let x: i16 = (bytes[1] as i16) << 8 | bytes[0] as i16;
|
||||||
|
let y: i16 = (bytes[3] as i16) << 8 | bytes[2] as i16;
|
||||||
|
let z: i16 = (bytes[5] as i16) << 8 | bytes[4] as i16;
|
||||||
|
Ok(XYZ { x, y, z })
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_register(&mut self, address: u8) -> Result<u8, I::Error> {
|
||||||
|
let mut value = [0u8];
|
||||||
|
self.interface.read(address, &mut value).await?;
|
||||||
|
Ok(value[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_register(&mut self, address: u8, value: u8) -> Result<(), I::Error> {
|
||||||
|
self.interface.write(address, value).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_register_config(&mut self, address: u8) -> Result<RegisterConfig, I::Error> {
|
||||||
|
let mut value = [0u8];
|
||||||
|
self.interface.read(address, &mut value).await?;
|
||||||
|
let value = value[0];
|
||||||
|
Ok(RegisterConfig { address, value })
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_register_config(
|
||||||
|
&mut self,
|
||||||
|
register_config: RegisterConfig,
|
||||||
|
) -> Result<(), I::Error> {
|
||||||
|
self.write_register(register_config.address, register_config.value)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interrupt sources
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum IrqSource {
|
||||||
|
FreeFall,
|
||||||
|
Sleep,
|
||||||
|
WakeUp,
|
||||||
|
WakeUpOnX,
|
||||||
|
WakeUpOnY,
|
||||||
|
WakeUpOnZ,
|
||||||
|
Tap,
|
||||||
|
SingleTap,
|
||||||
|
DoubleTap,
|
||||||
|
TapOnX,
|
||||||
|
TapOnY,
|
||||||
|
TapOnZ,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// pub struct IrqSources(pub Vec<IrqSource>);
|
540
tflite_demo/lsm6ds3tr/registers/addresses.rs
Normal file
540
tflite_demo/lsm6ds3tr/registers/addresses.rs
Normal file
@ -0,0 +1,540 @@
|
|||||||
|
/// Registers list
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum RegisterAddress {
|
||||||
|
// RESERVED = 0x00,
|
||||||
|
/// Embedded functions configuration register
|
||||||
|
FUNC_CFG_ACCESS = 0x01,
|
||||||
|
// RESERVED = [0x02..0x03],
|
||||||
|
/// Sensor sync configuration register
|
||||||
|
SENSOR_SYNC_TIME_FRAME = 0x04,
|
||||||
|
/// Sensor sync configuration register
|
||||||
|
SENSOR_SYNC_RES_RATIO = 0x05,
|
||||||
|
/// FIFO configuration registers
|
||||||
|
FIFO_CTRL1 = 0x06,
|
||||||
|
/// FIFO configuration registers
|
||||||
|
FIFO_CTRL2 = 0x07,
|
||||||
|
/// FIFO configuration registers
|
||||||
|
FIFO_CTRL3 = 0x08,
|
||||||
|
/// FIFO configuration registers
|
||||||
|
FIFO_CTRL4 = 0x09,
|
||||||
|
/// FIFO configuration registers
|
||||||
|
FIFO_CTRL5 = 0x0A,
|
||||||
|
/// (no comment)
|
||||||
|
DRDY_PULSE_CFG_G = 0x0B,
|
||||||
|
// RESERVED = 0x0C,
|
||||||
|
/// INT1 pin control
|
||||||
|
INT1_CTRL = 0x0D,
|
||||||
|
/// INT2 pin control
|
||||||
|
INT2_CTRL = 0x0E,
|
||||||
|
/// Who I am ID
|
||||||
|
WHO_AM_I = 0x0F,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL1_XL = 0x10,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL2_G = 0x11,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL3_C = 0x12,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL4_C = 0x13,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL5_C = 0x14,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL6_C = 0x15,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL7_G = 0x16,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL8_XL = 0x17,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL9_XL = 0x18,
|
||||||
|
/// Accelerometer and gyroscope control registers
|
||||||
|
CTRL10_C = 0x19,
|
||||||
|
/// I2C master configuration register
|
||||||
|
MASTER_CONFIG = 0x1A,
|
||||||
|
/// Interrupt registers
|
||||||
|
WAKE_UP_SRC = 0x1B,
|
||||||
|
/// Interrupt registers
|
||||||
|
TAP_SRC = 0x1C,
|
||||||
|
/// Interrupt registers
|
||||||
|
D6D_SRC = 0x1D,
|
||||||
|
/// Status data register for user interface
|
||||||
|
STATUS_REG = 0x1E,
|
||||||
|
// RESERVED = 0x1F,
|
||||||
|
/// Temperature output data registers
|
||||||
|
OUT_TEMP_L = 0x20,
|
||||||
|
/// Temperature output data registers
|
||||||
|
OUT_TEMP_H = 0x21,
|
||||||
|
/// Gyroscope output registers for user interface
|
||||||
|
OUTX_L_G = 0x22,
|
||||||
|
/// Gyroscope output registers for user interface
|
||||||
|
OUTX_H_G = 0x23,
|
||||||
|
/// Gyroscope output registers for user interface
|
||||||
|
OUTY_L_G = 0x24,
|
||||||
|
/// Gyroscope output registers for user interface
|
||||||
|
OUTY_H_G = 0x25,
|
||||||
|
/// Gyroscope output registers for user interface
|
||||||
|
OUTZ_L_G = 0x26,
|
||||||
|
/// Gyroscope output registers for user interface
|
||||||
|
OUTZ_H_G = 0x27,
|
||||||
|
/// Accelerometer output registers
|
||||||
|
OUTX_L_XL = 0x28,
|
||||||
|
/// Accelerometer output registers
|
||||||
|
OUTX_H_XL = 0x29,
|
||||||
|
/// Accelerometer output registers
|
||||||
|
OUTY_L_XL = 0x2A,
|
||||||
|
/// Accelerometer output registers
|
||||||
|
OUTY_H_XL = 0x2B,
|
||||||
|
/// Accelerometer output registers
|
||||||
|
OUTZ_L_XL = 0x2C,
|
||||||
|
/// Accelerometer output registers
|
||||||
|
OUTZ_H_XL = 0x2D,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB1_REG = 0x2E,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB2_REG = 0x2F,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB3_REG = 0x30,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB4_REG = 0x31,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB5_REG = 0x32,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB6_REG = 0x33,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB7_REG = 0x34,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB8_REG = 0x35,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB9_REG = 0x36,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB10_REG = 0x37,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB11_REG = 0x38,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB12_REG = 0x39,
|
||||||
|
/// FIFO status registers
|
||||||
|
FIFO_STATUS1 = 0x3A,
|
||||||
|
/// FIFO status registers
|
||||||
|
FIFO_STATUS2 = 0x3B,
|
||||||
|
/// FIFO status registers
|
||||||
|
FIFO_STATUS3 = 0x3C,
|
||||||
|
/// FIFO status registers
|
||||||
|
FIFO_STATUS4 = 0x3D,
|
||||||
|
/// FIFO data output registers
|
||||||
|
FIFO_DATA_OUT_L = 0x3E,
|
||||||
|
/// FIFO data output registers
|
||||||
|
FIFO_DATA_OUT_H = 0x3F,
|
||||||
|
/// Timestamp output registers
|
||||||
|
TIMESTAMP0_REG = 0x40,
|
||||||
|
/// Timestamp output registers
|
||||||
|
TIMESTAMP1_REG = 0x41,
|
||||||
|
/// Timestamp output registers
|
||||||
|
TIMESTAMP2_REG = 0x42,
|
||||||
|
// RESERVED = [0x43..0x48],
|
||||||
|
/// Step counter timestamp registers
|
||||||
|
STEP_TIMESTAMP_L = 0x49,
|
||||||
|
/// Step counter timestamp registers
|
||||||
|
STEP_TIMESTAMP_H = 0x4A,
|
||||||
|
/// Step counter output registers
|
||||||
|
STEP_COUNTER_L = 0x4B,
|
||||||
|
/// Step counter output registers
|
||||||
|
STEP_COUNTER_H = 0x4C,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB13_REG = 0x4D,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB14_REG = 0x4E,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB15_REG = 0x4F,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB16_REG = 0x50,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB17_REG = 0x51,
|
||||||
|
/// Sensor hub output registers
|
||||||
|
SENSORHUB18_REG = 0x52,
|
||||||
|
/// Interrupt registers
|
||||||
|
FUNC_SRC1 = 0x53,
|
||||||
|
/// Interrupt registers
|
||||||
|
FUNC_SRC2 = 0x54,
|
||||||
|
/// Interrupt register
|
||||||
|
WRIST_TILT_IA = 0x55,
|
||||||
|
// RESERVED = [0x56..0x57],
|
||||||
|
/// Interrupt registers
|
||||||
|
TAP_CFG = 0x58,
|
||||||
|
/// Interrupt registers
|
||||||
|
TAP_THS_6D = 0x59,
|
||||||
|
/// Interrupt registers
|
||||||
|
INT_DUR2 = 0x5A,
|
||||||
|
/// Interrupt registers
|
||||||
|
WAKE_UP_THS = 0x5B,
|
||||||
|
/// Interrupt registers
|
||||||
|
WAKE_UP_DUR = 0x5C,
|
||||||
|
/// Interrupt registers
|
||||||
|
FREE_FALL = 0x5D,
|
||||||
|
/// Interrupt registers
|
||||||
|
MD1_CFG = 0x5E,
|
||||||
|
/// Interrupt registers
|
||||||
|
MD2_CFG = 0x5F,
|
||||||
|
/// (no comment)
|
||||||
|
MASTER_CMD_CODE = 0x60,
|
||||||
|
/// (no comment)
|
||||||
|
SENS_SYNC_SPI_ERROR_CODE = 0x61,
|
||||||
|
// RESERVED = [0x62..0x65],
|
||||||
|
/// External magnetometer raw data output registers
|
||||||
|
OUT_MAG_RAW_X_L = 0x66,
|
||||||
|
/// External magnetometer raw data output registers
|
||||||
|
OUT_MAG_RAW_X_H = 0x67,
|
||||||
|
/// External magnetometer raw data output registers
|
||||||
|
OUT_MAG_RAW_Y_L = 0x68,
|
||||||
|
/// External magnetometer raw data output registers
|
||||||
|
OUT_MAG_RAW_Y_H = 0x69,
|
||||||
|
/// External magnetometer raw data output registers
|
||||||
|
OUT_MAG_RAW_Z_L = 0x6A,
|
||||||
|
/// External magnetometer raw data output registers
|
||||||
|
OUT_MAG_RAW_Z_H = 0x6B,
|
||||||
|
// RESERVED = [0x6C..0x72],
|
||||||
|
/// Accelerometer user offset correction
|
||||||
|
X_OFS_USR = 0x73,
|
||||||
|
/// Accelerometer user offset correction
|
||||||
|
Y_OFS_USR = 0x74,
|
||||||
|
/// Accelerometer user offset correction
|
||||||
|
Z_OFS_USR = 0x75,
|
||||||
|
// RESERVED = [0x76..0x7F],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterAddress {
|
||||||
|
pub fn address(self) -> u8 {
|
||||||
|
self as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register address+value container
|
||||||
|
pub struct RegisterConfig {
|
||||||
|
pub address: u8,
|
||||||
|
pub value: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simple bit-field structure
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RegisterBits<const BITS_NUM: u8, const BITS_POS: u8> {
|
||||||
|
value: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const BITS_NUM: u8, const BITS_POS: u8> RegisterBits<BITS_NUM, BITS_POS> {
|
||||||
|
/// New object with (unshifted) value set
|
||||||
|
pub fn new(value: u8) -> Self {
|
||||||
|
Self::from(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// New object with value set by extracting (shifting) relevant bits from register value
|
||||||
|
pub fn from_reg(value: u8) -> Self {
|
||||||
|
let mut s = Self::default();
|
||||||
|
s.set_from_reg(value);
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets value by extracting (shifting) relevant bits from register value
|
||||||
|
pub fn set_from_reg(&mut self, value: u8) {
|
||||||
|
self.value = (value >> BITS_POS) & Self::bit_mask();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns unshifted value
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns unshifted bit mask
|
||||||
|
pub fn bit_mask() -> u8 {
|
||||||
|
(1 << BITS_NUM) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns shifted bit mask
|
||||||
|
pub fn bit_shifted_mask() -> u8 {
|
||||||
|
Self::bit_mask() << BITS_POS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait RegisterValue {
|
||||||
|
fn shifted(&self) -> u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const BITS_NUM: u8, const BITS_POS: u8> RegisterValue for RegisterBits<BITS_NUM, BITS_POS> {
|
||||||
|
/// Returns shifted value to be OR-ed into register value
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
(self.value & Self::bit_mask()) << BITS_POS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const BITS_NUM: u8, const BITS_POS: u8> From<u8> for RegisterBits<BITS_NUM, BITS_POS> {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
value: value & Self::bit_mask(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const BITS_NUM: u8, const BITS_POS: u8> From<bool> for RegisterBits<BITS_NUM, BITS_POS> {
|
||||||
|
fn from(value: bool) -> Self {
|
||||||
|
Self::from(value as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::{RegisterBits, RegisterValue};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_1_0() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_1_1() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_1_2() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 2;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_2_0() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_2_1() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_2_2() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 2;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shifted_1_0() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
assert_eq!(rb.shifted(), 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shifted_1_1() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
assert_eq!(rb.shifted(), 0b10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shifted_1_2() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 2;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
assert_eq!(rb.shifted(), 0b100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shifted_2_1() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b110);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn shifted_2_2() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 2;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::new(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b1100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_from_reg_1_0() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
assert_eq!(rb.shifted(), 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_from_reg_1_1() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
assert_eq!(rb.shifted(), 0b10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_from_reg_2_0() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_from_reg_2_1() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b110);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_from_reg_2_2() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 2;
|
||||||
|
let rb = RegisterBits::<BITS, POS>::from_reg(0b11111111);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b1100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_reg_1_0() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
let mut rb = RegisterBits::<BITS, POS>::default();
|
||||||
|
let reg: u8 = 0b11111111;
|
||||||
|
rb.set_from_reg(reg);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
assert_eq!(rb.shifted(), 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_reg_1_1() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let mut rb = RegisterBits::<BITS, POS>::default();
|
||||||
|
let reg: u8 = 0b11111111;
|
||||||
|
rb.set_from_reg(reg);
|
||||||
|
assert_eq!(rb.value, 0b1);
|
||||||
|
assert_eq!(rb.shifted(), 0b10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_reg_2_0() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
let mut rb = RegisterBits::<BITS, POS>::default();
|
||||||
|
let reg: u8 = 0b11111111;
|
||||||
|
rb.set_from_reg(reg);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_reg_2_1() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
let mut rb = RegisterBits::<BITS, POS>::default();
|
||||||
|
let reg: u8 = 0b11111111;
|
||||||
|
rb.set_from_reg(reg);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b110);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn from_reg_2_2() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 2;
|
||||||
|
let mut rb = RegisterBits::<BITS, POS>::default();
|
||||||
|
let reg: u8 = 0b11111111;
|
||||||
|
rb.set_from_reg(reg);
|
||||||
|
assert_eq!(rb.value, 0b11);
|
||||||
|
assert_eq!(rb.shifted(), 0b1100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_mask_1_0() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_mask(), 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_mask_2_0() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_mask(), 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_mask_3_0() {
|
||||||
|
const BITS: u8 = 3;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_mask(), 0b111);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_shifted_mask_1_0() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_shifted_mask_1_1() {
|
||||||
|
const BITS: u8 = 1;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b10);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_shifted_mask_2_0() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b11);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_shifted_mask_2_1() {
|
||||||
|
const BITS: u8 = 2;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b110);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_shifted_mask_3_0() {
|
||||||
|
const BITS: u8 = 3;
|
||||||
|
const POS: u8 = 0;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b111);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bit_shifted_mask_3_1() {
|
||||||
|
const BITS: u8 = 3;
|
||||||
|
const POS: u8 = 1;
|
||||||
|
assert_eq!(RegisterBits::<BITS, POS>::bit_shifted_mask(), 0b1110);
|
||||||
|
}
|
||||||
|
}
|
103
tflite_demo/lsm6ds3tr/registers/ctrl1_xl.rs
Normal file
103
tflite_demo/lsm6ds3tr/registers/ctrl1_xl.rs
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
//! Linear acceleration sensor control register 1 (r/w).
|
||||||
|
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Linear acceleration sensor control register 1 (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Ctrl1Xl {
|
||||||
|
/// Output data rate and power mode selection. Default value: 0000 (see Table 52).
|
||||||
|
pub sample_rate: AccelSampleRate,
|
||||||
|
/// Accelerometer full-scale selection. Default value: 00.
|
||||||
|
/// (00: ±2 g; 01: ±16 g; 10: ±4 g; 11: ±8 g)
|
||||||
|
pub scale: AccelScale,
|
||||||
|
/// Accelerometer digital LPF (LPF1) bandwidth selection. For bandwidth selection refer to CTRL8_XL (17h).
|
||||||
|
pub low_pass_filter: RegisterBits<1, 6>, // TODO
|
||||||
|
/// Accelerometer analog chain bandwidth selection (only for accelerometer ODR ≥ 1.67 kHz).
|
||||||
|
/// (0: BW @ 1.5 kHz; 1: BW @ 400 Hz)
|
||||||
|
pub analog_chain_bandwidth: RegisterBits<1, 7>, // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ctrl1Xl {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::CTRL1_XL.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.sample_rate.shifted()
|
||||||
|
| self.scale.shifted()
|
||||||
|
| self.low_pass_filter.shifted()
|
||||||
|
| self.analog_chain_bandwidth.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub enum AccelScale {
|
||||||
|
#[default]
|
||||||
|
_2G = 0b00,
|
||||||
|
_16G = 0b01,
|
||||||
|
_4G = 0b10,
|
||||||
|
_8G = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccelScale {
|
||||||
|
pub fn sensitivity(self) -> f32 {
|
||||||
|
use AccelScale::*;
|
||||||
|
match self {
|
||||||
|
_2G => 0.000_061,
|
||||||
|
_4G => 0.000_122,
|
||||||
|
_8G => 0.000_244,
|
||||||
|
_16G => 0.000_488,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterValue for AccelScale {
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
(*self as u8) << 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub enum AccelSampleRate {
|
||||||
|
/// Power Down (disabled)
|
||||||
|
#[default]
|
||||||
|
PowerDown = 0b0000,
|
||||||
|
/// 12.5 Hz
|
||||||
|
_12_5Hz = 0b0001,
|
||||||
|
/// 26 Hz
|
||||||
|
_26Hz = 0b0010,
|
||||||
|
/// 52 Hz
|
||||||
|
_52Hz = 0b0011,
|
||||||
|
/// 104 Hz
|
||||||
|
_104Hz = 0b0100,
|
||||||
|
/// 208 Hz
|
||||||
|
_208Hz = 0b0101,
|
||||||
|
/// 416 Hz
|
||||||
|
_416Hz = 0b0110,
|
||||||
|
/// 833 Hz
|
||||||
|
_833Hz = 0b0111,
|
||||||
|
/// 1.66 kHz
|
||||||
|
_1660Hz = 0b1000,
|
||||||
|
/// 3.33 kHz
|
||||||
|
_3330Hz = 0b1001,
|
||||||
|
/// 6.66 kHz
|
||||||
|
_6660Hz = 0b1010,
|
||||||
|
/// 1.6 Hz in low power mode; 12.5 Hz in high performance mode
|
||||||
|
_1_6Hz_LP_or_12_5Hz_HP = 0b1011,
|
||||||
|
// Not allowed = [0b1100..0b1111]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterValue for AccelSampleRate {
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
(*self as u8) << 4
|
||||||
|
}
|
||||||
|
}
|
98
tflite_demo/lsm6ds3tr/registers/ctrl2_g.rs
Normal file
98
tflite_demo/lsm6ds3tr/registers/ctrl2_g.rs
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
//! Angular rate sensor control register 2 (r/w).
|
||||||
|
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::registers::RegisterConfig;
|
||||||
|
use crate::lsm6ds3tr::RegisterAddress;
|
||||||
|
|
||||||
|
use super::RegisterValue;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
/// Angular rate sensor control register 2 (r/w).
|
||||||
|
pub struct Ctrl2G {
|
||||||
|
/// Gyroscope output data rate selection. Default value: 0000 (Refer to Table 55)
|
||||||
|
pub sample_rate: GyroSampleRate,
|
||||||
|
/// Gyroscope full-scale selection. Default value: 00 (00: 245 dps; 01: 500 dps; 10: 1000 dps; 11: 2000 dps)
|
||||||
|
/// Gyroscope full-scale at 125 dps. Default value: 0 (0: disabled; 1: enabled)
|
||||||
|
pub scale: GyroScale,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ctrl2G {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::CTRL2_G.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.sample_rate.shifted() | self.scale.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Copy)]
|
||||||
|
pub enum GyroScale {
|
||||||
|
_125DPS = 0b001,
|
||||||
|
#[default]
|
||||||
|
_250DPS = 0b000,
|
||||||
|
_500DPS = 0b010,
|
||||||
|
_1000DPS = 0b100,
|
||||||
|
_2000DPS = 0b110,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GyroScale {
|
||||||
|
pub fn sensitivity(self) -> f32 {
|
||||||
|
use GyroScale::*;
|
||||||
|
match self {
|
||||||
|
_125DPS => 0.004_375,
|
||||||
|
_250DPS => 0.008_750,
|
||||||
|
_500DPS => 0.017_500,
|
||||||
|
_1000DPS => 0.035_000,
|
||||||
|
_2000DPS => 0.070_000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterValue for GyroScale {
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
(*self as u8) << 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Copy)]
|
||||||
|
pub enum GyroSampleRate {
|
||||||
|
/// Power Down (disabled)
|
||||||
|
#[default]
|
||||||
|
PowerDown = 0b0000,
|
||||||
|
/// 12.5 Hz
|
||||||
|
_12_5Hz = 0b0001,
|
||||||
|
/// 26 Hz
|
||||||
|
_26Hz = 0b0010,
|
||||||
|
/// 52 Hz
|
||||||
|
_52Hz = 0b0011,
|
||||||
|
/// 104 Hz
|
||||||
|
_104Hz = 0b0100,
|
||||||
|
/// 208 Hz
|
||||||
|
_208Hz = 0b0101,
|
||||||
|
/// 416 Hz
|
||||||
|
_416Hz = 0b0110,
|
||||||
|
/// 833 Hz
|
||||||
|
_833Hz = 0b0111,
|
||||||
|
/// 1.66 kHz
|
||||||
|
_1660Hz = 0b1000,
|
||||||
|
/// 3.33 kHz
|
||||||
|
_3330Hz = 0b1001,
|
||||||
|
/// 6.66 kHz
|
||||||
|
_6660Hz = 0b1010,
|
||||||
|
// Not allowed = [0b1011..0b1111]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterValue for GyroSampleRate {
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
(*self as u8) << 4
|
||||||
|
}
|
||||||
|
}
|
73
tflite_demo/lsm6ds3tr/registers/ctrl3_c.rs
Normal file
73
tflite_demo/lsm6ds3tr/registers/ctrl3_c.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//! Control register 3 (r/w).
|
||||||
|
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Control register 3 (r/w).
|
||||||
|
pub struct Ctrl3C {
|
||||||
|
/// Reboot memory content. Default value: 0
|
||||||
|
/// (0: normal mode; 1: reboot memory content)
|
||||||
|
pub reboot_memory_content: RegisterBits<1, 7>,
|
||||||
|
/// Block Data Update. Default value: 0
|
||||||
|
/// (0: continuous update; 1: output registers not updated until MSB and LSB have been read)
|
||||||
|
pub block_data_update: RegisterBits<1, 6>,
|
||||||
|
/// Interrupt activation level. Default value: 0
|
||||||
|
/// (0: interrupt output pads active high; 1: interrupt output pads active low)
|
||||||
|
pub high_low_active: RegisterBits<1, 5>,
|
||||||
|
/// Push-pull/open-drain selection on INT1 and INT2 pads. Default value: 0
|
||||||
|
/// (0: push-pull mode; 1: open-drain mode)
|
||||||
|
pub push_pull_open_drain: RegisterBits<1, 4>,
|
||||||
|
/// SPI Serial Interface Mode selection. Default value: 0
|
||||||
|
/// (0: 4-wire interface; 1: 3-wire interface).
|
||||||
|
pub spi_interface_mode: RegisterBits<1, 3>,
|
||||||
|
/// Register address automatically incremented during a multiple byte access with a serial interface (I2C or SPI). Default value: 1
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub interface_auto_address_increment: RegisterBits<1, 2>,
|
||||||
|
/// Big/Little Endian Data selection. Default value 0
|
||||||
|
/// (0: data LSB @ lower address; 1: data MSB @ lower address)
|
||||||
|
pub big_little_endian: RegisterBits<1, 1>,
|
||||||
|
/// Software reset. Default value: 0
|
||||||
|
/// (0: normal mode; 1: reset device)
|
||||||
|
/// This bit is automatically cleared.
|
||||||
|
pub software_reset: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Ctrl3C {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
interface_auto_address_increment: RegisterBits::new(1),
|
||||||
|
reboot_memory_content: RegisterBits::default(),
|
||||||
|
block_data_update: RegisterBits::default(),
|
||||||
|
high_low_active: RegisterBits::default(),
|
||||||
|
push_pull_open_drain: RegisterBits::default(),
|
||||||
|
spi_interface_mode: RegisterBits::default(),
|
||||||
|
big_little_endian: RegisterBits::default(),
|
||||||
|
software_reset: RegisterBits::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ctrl3C {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::CTRL3_C.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.reboot_memory_content.shifted()
|
||||||
|
| self.block_data_update.shifted()
|
||||||
|
| self.high_low_active.shifted()
|
||||||
|
| self.push_pull_open_drain.shifted()
|
||||||
|
| self.spi_interface_mode.shifted()
|
||||||
|
| self.interface_auto_address_increment.shifted()
|
||||||
|
| self.big_little_endian.shifted()
|
||||||
|
| self.software_reset.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
tflite_demo/lsm6ds3tr/registers/ctrl4_c.rs
Normal file
56
tflite_demo/lsm6ds3tr/registers/ctrl4_c.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//! Control register 4 (r/w).
|
||||||
|
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Control register 4 (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Ctrl4C {
|
||||||
|
/// Extend DEN functionality to accelerometer sensor. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub extend_den: RegisterBits<1, 7>,
|
||||||
|
/// Gyroscope sleep mode enable. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub gyroscope_sleep: RegisterBits<1, 6>,
|
||||||
|
/// DEN DRDY signal on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub den_data_ready_int1: RegisterBits<1, 5>,
|
||||||
|
/// All interrupt signals available on INT1 pad enable. Default value: 0
|
||||||
|
/// (0: interrupt signals divided between INT1 and INT2 pads;
|
||||||
|
/// 1: all interrupt signals in logic or on INT1 pad)
|
||||||
|
pub int2_on_int1: RegisterBits<1, 4>,
|
||||||
|
/// Configuration 1 data available enable bit. Default value: 0
|
||||||
|
/// (0: DA timer disabled; 1: DA timer enabled)
|
||||||
|
pub data_ready_mask: RegisterBits<1, 3>,
|
||||||
|
/// Disable I2C interface. Default value: 0
|
||||||
|
/// (0: both I2C and SPI enabled; 1: I2C disabled, SPI only enabled)
|
||||||
|
pub i2c_disable: RegisterBits<1, 2>,
|
||||||
|
/// Enable gyroscope digital LPF1. The bandwidth can be selected through
|
||||||
|
/// FTYPE[1\:0] in FUNC_CFG_ACCESS (01h).
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub gyroscope_low_pass_filter_selection: RegisterBits<1, 1>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ctrl4C {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::CTRL4_C.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.extend_den.shifted()
|
||||||
|
| self.gyroscope_sleep.shifted()
|
||||||
|
| self.den_data_ready_int1.shifted()
|
||||||
|
| self.int2_on_int1.shifted()
|
||||||
|
| self.data_ready_mask.shifted()
|
||||||
|
| self.i2c_disable.shifted()
|
||||||
|
| self.gyroscope_low_pass_filter_selection.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
tflite_demo/lsm6ds3tr/registers/drdy_pulse_cfg_g.rs
Normal file
34
tflite_demo/lsm6ds3tr/registers/drdy_pulse_cfg_g.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//! DataReady configuration register (r/w).
|
||||||
|
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// DataReady configuration register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DrdyPulseCfgG {
|
||||||
|
/// Enable pulsed DataReady mode. Default value: 0
|
||||||
|
/// (0: DataReady latched mode. Returns to 0 only after output data have been read;
|
||||||
|
/// 1: DataReady pulsed mode. The DataReady pulses are 75 μs long.)
|
||||||
|
pub pulsed_data_ready: RegisterBits<1, 7>,
|
||||||
|
/// Wrist tilt interrupt on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub int2_wrist_tilt: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrdyPulseCfgG {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::DRDY_PULSE_CFG_G.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.pulsed_data_ready.shifted() | self.int2_wrist_tilt.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
tflite_demo/lsm6ds3tr/registers/free_fall.rs
Normal file
52
tflite_demo/lsm6ds3tr/registers/free_fall.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//! Free-fall function duration setting register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Free-fall function duration setting register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct FreeFall {
|
||||||
|
/// Free-fall duration event. Default: 0
|
||||||
|
/// For the complete configuration of the free fall duration, refer to FF_DUR5 in WAKE_UP_DUR (5Ch) configuration
|
||||||
|
pub duration_event: RegisterBits<5, 3>,
|
||||||
|
/// Free fall threshold setting. Default: 000
|
||||||
|
/// For details refer to Table 196.
|
||||||
|
pub threshold: FreeFallThreshold,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FreeFall {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::FREE_FALL.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.duration_event.shifted() | self.threshold.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub enum FreeFallThreshold {
|
||||||
|
#[default]
|
||||||
|
_156_mg = 0b000,
|
||||||
|
_219_mg = 0b001,
|
||||||
|
_250_mg = 0b010,
|
||||||
|
_312_mg = 0b011,
|
||||||
|
_344_mg = 0b100,
|
||||||
|
_406_mg = 0b101,
|
||||||
|
_469_mg = 0b110,
|
||||||
|
_500_mg = 0b111,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterValue for FreeFallThreshold {
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
}
|
57
tflite_demo/lsm6ds3tr/registers/int1_ctrl.rs
Normal file
57
tflite_demo/lsm6ds3tr/registers/int1_ctrl.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//! INT1 pad control register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// INT1 pad control register (r/w).
|
||||||
|
/// Each bit in this register enables a signal to be carried through INT1. The pad’s output will supply the OR combination of the selected signals.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Int1Ctrl {
|
||||||
|
/// Pedometer step recognition interrupt enable on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub pedometer_step_recognition: RegisterBits<1, 7>,
|
||||||
|
/// Significant motion interrupt enable on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub significant_motion: RegisterBits<1, 6>,
|
||||||
|
/// FIFO full flag interrupt enable on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub fifo_full: RegisterBits<1, 5>,
|
||||||
|
/// FIFO overrun interrupt on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub fifo_overrun: RegisterBits<1, 4>,
|
||||||
|
/// FIFO threshold interrupt on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub fifo_threshold: RegisterBits<1, 3>,
|
||||||
|
/// Boot status available on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub boot_status_available: RegisterBits<1, 2>,
|
||||||
|
/// Gyroscope Data Ready on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub gyroscope_data_ready: RegisterBits<1, 1>,
|
||||||
|
/// Accelerometer Data Ready on INT1 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub accelerometer_data_ready: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Int1Ctrl {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::INT1_CTRL.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.pedometer_step_recognition.shifted()
|
||||||
|
| self.significant_motion.shifted()
|
||||||
|
| self.fifo_full.shifted()
|
||||||
|
| self.fifo_overrun.shifted()
|
||||||
|
| self.fifo_threshold.shifted()
|
||||||
|
| self.boot_status_available.shifted()
|
||||||
|
| self.gyroscope_data_ready.shifted()
|
||||||
|
| self.accelerometer_data_ready.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
tflite_demo/lsm6ds3tr/registers/int2_ctrl.rs
Normal file
57
tflite_demo/lsm6ds3tr/registers/int2_ctrl.rs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//! INT2 pad control register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// INT2 pad control register (r/w).
|
||||||
|
/// Each bit in this register enables a signal to be carried through INT2. The pad’s output will supply the OR combination of the selected signals.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Int2Ctrl {
|
||||||
|
/// Pedometer step recognition interrupt on delta time(1) enable on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub pedometer_step_recognition_delta_time: RegisterBits<1, 7>,
|
||||||
|
/// Step counter overflow interrupt enable on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub step_counter_overflow: RegisterBits<1, 6>,
|
||||||
|
/// FIFO full flag interrupt enable on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub fifo_full: RegisterBits<1, 5>,
|
||||||
|
/// FIFO overrun interrupt on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub fifo_overrun: RegisterBits<1, 4>,
|
||||||
|
/// FIFO threshold interrupt on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub fifo_threshold: RegisterBits<1, 3>,
|
||||||
|
/// Temperature Data Ready on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub temperature_data_ready: RegisterBits<1, 2>,
|
||||||
|
/// Gyroscope Data Ready on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub gyroscope_data_ready: RegisterBits<1, 1>,
|
||||||
|
/// Accelerometer Data Ready on INT2 pad. Default value: 0
|
||||||
|
/// (0: disabled; 1: enabled)
|
||||||
|
pub accelerometer_data_ready: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Int2Ctrl {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::INT2_CTRL.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.pedometer_step_recognition_delta_time.shifted()
|
||||||
|
| self.step_counter_overflow.shifted()
|
||||||
|
| self.fifo_full.shifted()
|
||||||
|
| self.fifo_overrun.shifted()
|
||||||
|
| self.fifo_threshold.shifted()
|
||||||
|
| self.temperature_data_ready.shifted()
|
||||||
|
| self.gyroscope_data_ready.shifted()
|
||||||
|
| self.accelerometer_data_ready.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
tflite_demo/lsm6ds3tr/registers/int_dur2.rs
Normal file
34
tflite_demo/lsm6ds3tr/registers/int_dur2.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//! Tap recognition function setting register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Tap recognition function setting register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct IntDur2 {
|
||||||
|
/// Duration of maximum time gap for double tap recognition. Default: 0000
|
||||||
|
/// When double tap recognition is enabled, this register expresses the maximum time between two consecutive detected taps to determine a double tap event. The default value of these bits is 0000b which corresponds to 16*ODR_XL time. If the DUR[3\:0] bits are set to a different value, 1LSB corresponds to 32*ODR_XL time.
|
||||||
|
pub duration: RegisterBits<4, 4>,
|
||||||
|
/// Expected quiet time after a tap detection. Default value: 00
|
||||||
|
/// Quiet time is the time after the first detected tap in which there must not be any overthreshold event. The default value of these bits is 00b which corresponds to 2*ODR_XL time. If the QUIET[1\:0] bits are set to a different value, 1LSB corresponds to 4*ODR_XL time.
|
||||||
|
pub quiet: RegisterBits<2, 2>,
|
||||||
|
/// Maximum duration of overthreshold event. Default value: 00
|
||||||
|
/// Maximum duration is the maximum time of an overthreshold signal detection to be recognized as a tap event. The default value of these bits is 00b which corresponds to 4*ODR_XL time. If the SHOCK[1\:0] bits are set to a different value, 1LSB corresponds to 8*ODR_XL time.
|
||||||
|
pub shock: RegisterBits<2, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntDur2 {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::INT_DUR2.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.duration.shifted() | self.quiet.shifted() | self.shock.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
tflite_demo/lsm6ds3tr/registers/md1_cfg.rs
Normal file
61
tflite_demo/lsm6ds3tr/registers/md1_cfg.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//! Function routing on INT1 register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Function routing on INT1 register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Md1Cfg {
|
||||||
|
/// Routing on INT1 of inactivity mode. Default: 0
|
||||||
|
/// (0: routing on INT1 of inactivity disabled; 1: routing on INT1 of inactivity enabled)
|
||||||
|
pub inactivity_event: RegisterBits<1, 7>,
|
||||||
|
/// Single-tap recognition routing on INT1. Default: 0
|
||||||
|
/// (0: routing of single-tap event on INT1 disabled;
|
||||||
|
/// 1: routing of single-tap event on INT1 enabled)
|
||||||
|
pub single_tap_event: RegisterBits<1, 6>,
|
||||||
|
/// Routing of wakeup event on INT1. Default value: 0
|
||||||
|
/// (0: routing of wakeup event on INT1 disabled;
|
||||||
|
/// 1: routing of wakeup event on INT1 enabled)
|
||||||
|
pub wake_up_event: RegisterBits<1, 5>,
|
||||||
|
/// Routing of free-fall event on INT1. Default value: 0
|
||||||
|
/// (0: routing of free-fall event on INT1 disabled;
|
||||||
|
/// 1: routing of free-fall event on INT1 enabled)
|
||||||
|
pub free_fall_event: RegisterBits<1, 4>,
|
||||||
|
/// Routing of tap event on INT1. Default value: 0
|
||||||
|
/// (0: routing of double-tap event on INT1 disabled;
|
||||||
|
/// 1: routing of double-tap event on INT1 enabled)
|
||||||
|
pub double_tap_event: RegisterBits<1, 3>,
|
||||||
|
/// Routing of 6D event on INT1. Default value: 0
|
||||||
|
/// (0: routing of 6D event on INT1 disabled; 1: routing of 6D event on INT1 enabled)
|
||||||
|
pub six_degrees_event: RegisterBits<1, 2>,
|
||||||
|
/// Routing of tilt event on INT1. Default value: 0
|
||||||
|
/// (0: routing of tilt event on INT1 disabled; 1: routing of tilt event on INT1 enabled)
|
||||||
|
pub tilt_event: RegisterBits<1, 1>,
|
||||||
|
/// Routing of end counter event of timer on INT1. Default value: 0
|
||||||
|
/// (0: routing of end counter event of timer on INT1 disabled;
|
||||||
|
/// 1: routing of end counter event of timer event on INT1 enabled)
|
||||||
|
pub timer_end_counter_event: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Md1Cfg {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::MD1_CFG.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.inactivity_event.shifted()
|
||||||
|
| self.single_tap_event.shifted()
|
||||||
|
| self.wake_up_event.shifted()
|
||||||
|
| self.free_fall_event.shifted()
|
||||||
|
| self.double_tap_event.shifted()
|
||||||
|
| self.six_degrees_event.shifted()
|
||||||
|
| self.tilt_event.shifted()
|
||||||
|
| self.timer_end_counter_event.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
tflite_demo/lsm6ds3tr/registers/md2_cfg.rs
Normal file
61
tflite_demo/lsm6ds3tr/registers/md2_cfg.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
//! Function routing on INT2 register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Function routing on INT2 register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Md2Cfg {
|
||||||
|
/// Routing on INT2 of inactivity mode. Default: 0
|
||||||
|
/// (0: routing on INT2 of inactivity disabled; 1: routing on INT2 of inactivity enabled)
|
||||||
|
pub inactivity_event: RegisterBits<1, 7>,
|
||||||
|
/// Single-tap recognition routing on INT2. Default: 0
|
||||||
|
/// (0: routing of single-tap event on INT2 disabled;
|
||||||
|
/// 1: routing of single-tap event on INT2 enabled)
|
||||||
|
pub single_tap_event: RegisterBits<1, 6>,
|
||||||
|
/// Routing of wakeup event on INT2. Default value: 0
|
||||||
|
/// (0: routing of wakeup event on INT2 disabled;
|
||||||
|
/// 1: routing of wake-up event on INT2 enabled)
|
||||||
|
pub wake_up_event: RegisterBits<1, 5>,
|
||||||
|
/// Routing of free-fall event on INT2. Default value: 0
|
||||||
|
/// (0: routing of free-fall event on INT2 disabled;
|
||||||
|
/// 1: routing of free-fall event on INT2 enabled)
|
||||||
|
pub free_fall_event: RegisterBits<1, 4>,
|
||||||
|
/// Routing of tap event on INT2. Default value: 0
|
||||||
|
/// (0: routing of double-tap event on INT2 disabled;
|
||||||
|
/// 1: routing of double-tap event on INT2 enabled)
|
||||||
|
pub double_tap_event: RegisterBits<1, 3>,
|
||||||
|
/// Routing of 6D event on INT2. Default value: 0
|
||||||
|
/// (0: routing of 6D event on INT2 disabled; 1: routing of 6D event on INT2 enabled)
|
||||||
|
pub six_degrees_event: RegisterBits<1, 2>,
|
||||||
|
/// Routing of tilt event on INT2. Default value: 0
|
||||||
|
/// (0: routing of tilt event on INT2 disabled; 1: routing of tilt event on INT2 enabled)
|
||||||
|
pub tilt_event: RegisterBits<1, 1>,
|
||||||
|
/// Routing of soft-iron/hard-iron algorithm end event on INT2. Default value: 0
|
||||||
|
/// (0: routing of soft-iron/hard-iron algorithm end event on INT2 disabled;
|
||||||
|
/// 1: routing of soft-iron/hard-iron algorithm end event on INT2 enabled)
|
||||||
|
pub soft_hard_iron_algorithm_end_event: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Md2Cfg {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::MD2_CFG.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.inactivity_event.shifted()
|
||||||
|
| self.single_tap_event.shifted()
|
||||||
|
| self.wake_up_event.shifted()
|
||||||
|
| self.free_fall_event.shifted()
|
||||||
|
| self.double_tap_event.shifted()
|
||||||
|
| self.six_degrees_event.shifted()
|
||||||
|
| self.tilt_event.shifted()
|
||||||
|
| self.soft_hard_iron_algorithm_end_event.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
tflite_demo/lsm6ds3tr/registers/mod.rs
Normal file
37
tflite_demo/lsm6ds3tr/registers/mod.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
pub mod addresses;
|
||||||
|
pub mod ctrl1_xl;
|
||||||
|
pub mod ctrl2_g;
|
||||||
|
pub mod ctrl3_c;
|
||||||
|
pub mod ctrl4_c;
|
||||||
|
pub mod drdy_pulse_cfg_g;
|
||||||
|
pub mod free_fall;
|
||||||
|
pub mod int1_ctrl;
|
||||||
|
pub mod int2_ctrl;
|
||||||
|
pub mod int_dur2;
|
||||||
|
pub mod md1_cfg;
|
||||||
|
pub mod md2_cfg;
|
||||||
|
pub mod tap_cfg;
|
||||||
|
pub mod tap_src;
|
||||||
|
pub mod tap_ths_6d;
|
||||||
|
pub mod wake_up_dur;
|
||||||
|
pub mod wake_up_src;
|
||||||
|
pub mod wake_up_ths;
|
||||||
|
|
||||||
|
pub use addresses::*;
|
||||||
|
pub use ctrl1_xl::*;
|
||||||
|
pub use ctrl2_g::*;
|
||||||
|
pub use ctrl3_c::*;
|
||||||
|
pub use ctrl4_c::*;
|
||||||
|
pub use drdy_pulse_cfg_g::*;
|
||||||
|
pub use free_fall::*;
|
||||||
|
pub use int1_ctrl::*;
|
||||||
|
pub use int2_ctrl::*;
|
||||||
|
pub use int_dur2::*;
|
||||||
|
pub use md1_cfg::*;
|
||||||
|
pub use md2_cfg::*;
|
||||||
|
pub use tap_cfg::*;
|
||||||
|
pub use tap_src::*;
|
||||||
|
pub use tap_ths_6d::*;
|
||||||
|
pub use wake_up_dur::*;
|
||||||
|
pub use wake_up_src::*;
|
||||||
|
pub use wake_up_ths::*;
|
85
tflite_demo/lsm6ds3tr/registers/tap_cfg.rs
Normal file
85
tflite_demo/lsm6ds3tr/registers/tap_cfg.rs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//! Enables interrupt and inactivity functions, configuration of filtering and tap recognition functions (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Enables interrupt and inactivity functions, configuration of filtering and tap recognition functions (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct TapCfg {
|
||||||
|
/// Enable basic interrupts (6D/4D, free-fall, wake-up, tap, inactivity). Default 0.
|
||||||
|
/// (0: interrupt disabled; 1: interrupt enabled)
|
||||||
|
pub enable_basic_interrupts: RegisterBits<1, 7>,
|
||||||
|
/// Enable inactivity function. Default value: 00
|
||||||
|
/// (00: disabled
|
||||||
|
/// 01: sets accelerometer ODR to 12.5 Hz (low-power mode), gyro does not change;
|
||||||
|
/// 10: sets accelerometer ODR to 12.5 Hz (low-power mode), gyro to sleep mode;
|
||||||
|
/// 11: sets accelerometer ODR to 12.5 Hz (low-power mode), gyro to power-down mode)
|
||||||
|
pub enable_inactivity_function: InactivityFunctionMode,
|
||||||
|
/// HPF or SLOPE filter selection on wake-up and Activity/Inactivity functions. Refer to Figure 8. Default value: 0
|
||||||
|
/// (0: SLOPE filter applied; 1: HPF applied)
|
||||||
|
pub slope_fds: FilterSelected,
|
||||||
|
/// Enable X direction in tap recognition. Default value: 0
|
||||||
|
/// (0: X direction disabled; 1: X direction enabled)
|
||||||
|
pub enable_x_direction_tap_recognition: RegisterBits<1, 3>,
|
||||||
|
/// Enable Y direction in tap recognition. Default value: 0
|
||||||
|
/// (0: Y direction disabled; 1: Y direction enabled)
|
||||||
|
pub enable_y_direction_tap_recognition: RegisterBits<1, 2>,
|
||||||
|
/// Enable Z direction in tap recognition. Default value: 0
|
||||||
|
/// (0: Z direction disabled; 1: Z direction enabled)
|
||||||
|
pub enable_z_direction_tap_recognition: RegisterBits<1, 1>,
|
||||||
|
/// Latched Interrupt. Default value: 0
|
||||||
|
/// (0: interrupt request not latched; 1: interrupt request latched)
|
||||||
|
pub latched_interrupt: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TapCfg {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::TAP_CFG.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.enable_basic_interrupts.shifted()
|
||||||
|
| self.enable_inactivity_function.shifted()
|
||||||
|
| self.slope_fds.shifted()
|
||||||
|
| self.enable_x_direction_tap_recognition.shifted()
|
||||||
|
| self.enable_y_direction_tap_recognition.shifted()
|
||||||
|
| self.enable_z_direction_tap_recognition.shifted()
|
||||||
|
| self.latched_interrupt.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub enum InactivityFunctionMode {
|
||||||
|
#[default]
|
||||||
|
Disabled = 0b00,
|
||||||
|
AccelLowPowerGyroUnchanged = 0b01,
|
||||||
|
AccelLowPowerGyroSleepMode = 0b10,
|
||||||
|
AccelLowPowerGyroPowerDown = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterValue for InactivityFunctionMode {
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
(*self as u8) << 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub enum FilterSelected {
|
||||||
|
#[default]
|
||||||
|
Slope = 0b0,
|
||||||
|
HighPassFilter = 0b1,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterValue for FilterSelected {
|
||||||
|
fn shifted(&self) -> u8 {
|
||||||
|
(*self as u8) << 4
|
||||||
|
}
|
||||||
|
}
|
73
tflite_demo/lsm6ds3tr/registers/tap_src.rs
Normal file
73
tflite_demo/lsm6ds3tr/registers/tap_src.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//! Tap source register (r).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{IrqSource, RegisterAddress, RegisterBits};
|
||||||
|
|
||||||
|
/// Tap source register (r).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct TapSrc {
|
||||||
|
/// Tap event detection status. Default: 0
|
||||||
|
/// (0: tap event not detected; 1: tap event detected)
|
||||||
|
pub tap_event: RegisterBits<1, 6>,
|
||||||
|
/// Single-tap event status. Default value: 0
|
||||||
|
/// (0: single tap event not detected; 1: single tap event detected)
|
||||||
|
pub single_tap_event: RegisterBits<1, 5>,
|
||||||
|
/// Double-tap event detection status. Default value: 0
|
||||||
|
/// (0: double-tap event not detected; 1: double-tap event detected.)
|
||||||
|
pub double_tap_event: RegisterBits<1, 4>,
|
||||||
|
/// Sign of acceleration detected by tap event. Default: 0
|
||||||
|
/// (0: positive sign of acceleration detected by tap event;
|
||||||
|
/// 1: negative sign of acceleration detected by tap event)
|
||||||
|
pub tap_sign_acceleration: RegisterBits<1, 3>,
|
||||||
|
/// Tap event detection status on X-axis. Default value: 0
|
||||||
|
/// (0: tap event on X-axis not detected; 1: tap event on X-axis detected)
|
||||||
|
pub tap_x_axis: RegisterBits<1, 2>,
|
||||||
|
/// Tap event detection status on Y-axis. Default value: 0
|
||||||
|
/// (0: tap event on Y-axis not detected; 1: tap event on Y-axis detected)
|
||||||
|
pub tap_y_axis: RegisterBits<1, 1>,
|
||||||
|
/// Tap event detection status on Z-axis. Default value: 0
|
||||||
|
/// (0: tap event on Z-axis not detected; 1: tap event on Z-axis detected)
|
||||||
|
pub tap_z_axis: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TapSrc {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::TAP_SRC.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn get_irq_sources(&self) -> Vec<IrqSource> {
|
||||||
|
// let mut v: Vec<IrqSource> = Default::default();
|
||||||
|
// if self.tap_event.value() != 0 {
|
||||||
|
// v.push(IrqSource::Tap);
|
||||||
|
// }
|
||||||
|
// if self.single_tap_event.value() != 0 {
|
||||||
|
// v.push(IrqSource::SingleTap);
|
||||||
|
// }
|
||||||
|
// if self.double_tap_event.value() != 0 {
|
||||||
|
// v.push(IrqSource::DoubleTap);
|
||||||
|
// }
|
||||||
|
// if self.tap_x_axis.value() != 0 {
|
||||||
|
// v.push(IrqSource::TapOnX);
|
||||||
|
// }
|
||||||
|
// if self.tap_y_axis.value() != 0 {
|
||||||
|
// v.push(IrqSource::TapOnY);
|
||||||
|
// }
|
||||||
|
// if self.tap_z_axis.value() != 0 {
|
||||||
|
// v.push(IrqSource::TapOnZ);
|
||||||
|
// }
|
||||||
|
// v
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for TapSrc {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
let mut s = Self::default();
|
||||||
|
s.tap_event.set_from_reg(value);
|
||||||
|
s.single_tap_event.set_from_reg(value);
|
||||||
|
s.double_tap_event.set_from_reg(value);
|
||||||
|
s.tap_sign_acceleration.set_from_reg(value);
|
||||||
|
s.tap_x_axis.set_from_reg(value);
|
||||||
|
s.tap_y_axis.set_from_reg(value);
|
||||||
|
s.tap_z_axis.set_from_reg(value);
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
36
tflite_demo/lsm6ds3tr/registers/tap_ths_6d.rs
Normal file
36
tflite_demo/lsm6ds3tr/registers/tap_ths_6d.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
//! Portrait/landscape position and tap function threshold register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Portrait/landscape position and tap function threshold register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct TapThs6d {
|
||||||
|
/// 4D orientation detection enable. Z-axis position detection is disabled. Default value: 0
|
||||||
|
/// (0: enabled; 1: disabled)
|
||||||
|
pub four_degrees_detection_enable: RegisterBits<1, 7>,
|
||||||
|
/// Threshold for 4D/6D function. Default value: 00
|
||||||
|
/// For details, refer to Table 187.
|
||||||
|
pub six_degrees_threshold: RegisterBits<2, 5>,
|
||||||
|
/// Threshold for tap recognition. Default value: 00000
|
||||||
|
/// 1 LSb corresponds to FS_XL/2^5
|
||||||
|
pub tap_threshold: RegisterBits<5, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TapThs6d {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::TAP_THS_6D.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.four_degrees_detection_enable.shifted()
|
||||||
|
| self.six_degrees_threshold.shifted()
|
||||||
|
| self.tap_threshold.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
tflite_demo/lsm6ds3tr/registers/wake_up_dur.rs
Normal file
41
tflite_demo/lsm6ds3tr/registers/wake_up_dur.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//! Free-fall, wakeup, timestamp and sleep mode functions duration setting register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Free-fall, wakeup, timestamp and sleep mode functions duration setting register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WakeUpDur {
|
||||||
|
/// Free fall duration event. Default: 0
|
||||||
|
/// For the complete configuration of the free-fall duration, refer to FF_DUR[4\:0] in FREE_FALL (5Dh) configuration.
|
||||||
|
/// 1 LSB = 1 ODR_time
|
||||||
|
pub free_fall_duration_event: RegisterBits<1, 7>,
|
||||||
|
/// Wake up duration event. Default: 00
|
||||||
|
/// 1LSB = 1 ODR_time
|
||||||
|
pub wake_up_duration_event: RegisterBits<2, 5>,
|
||||||
|
/// Timestamp register resolution setting. Default value: 0
|
||||||
|
/// (0: 1LSB = 6.4 ms; 1: 1LSB = 25 μs)
|
||||||
|
pub timestamp_resolution: RegisterBits<1, 4>,
|
||||||
|
/// Duration to go in sleep mode. Default value: 0000 (this corresponds to 16 ODR)
|
||||||
|
/// 1 LSB = 512 ODR
|
||||||
|
pub sleep_duration_event: RegisterBits<4, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WakeUpDur {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::WAKE_UP_DUR.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.free_fall_duration_event.shifted()
|
||||||
|
| self.wake_up_duration_event.shifted()
|
||||||
|
| self.timestamp_resolution.shifted()
|
||||||
|
| self.sleep_duration_event.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
tflite_demo/lsm6ds3tr/registers/wake_up_src.rs
Normal file
69
tflite_demo/lsm6ds3tr/registers/wake_up_src.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
//! Wake up interrupt source register (r).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{IrqSource, RegisterAddress, RegisterBits};
|
||||||
|
|
||||||
|
/// Wake up interrupt source register (r).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WakeUpSrc {
|
||||||
|
/// Free-fall event detection status. Default: 0
|
||||||
|
/// (0: free-fall event not detected; 1: free-fall event detected)
|
||||||
|
pub free_fall_event: RegisterBits<1, 5>,
|
||||||
|
/// Sleep event status. Default value: 0
|
||||||
|
/// (0: sleep event not detected; 1: sleep event detected)
|
||||||
|
pub sleep_event: RegisterBits<1, 4>,
|
||||||
|
/// Wakeup event detection status. Default value: 0
|
||||||
|
/// (0: wakeup event not detected; 1: wakeup event detected.)
|
||||||
|
pub wake_up_event: RegisterBits<1, 3>,
|
||||||
|
/// Wakeup event detection status on X-axis. Default value: 0
|
||||||
|
/// (0: wakeup event on X-axis not detected; 1: wakeup event on X-axis detected)
|
||||||
|
pub wake_up_event_x: RegisterBits<1, 2>,
|
||||||
|
/// Wakeup event detection status on Y-axis. Default value: 0
|
||||||
|
/// (0: wakeup event on Y-axis not detected; 1: wakeup event on Y-axis detected)
|
||||||
|
pub wake_up_event_y: RegisterBits<1, 1>,
|
||||||
|
/// Wakeup event detection status on Z-axis. Default value: 0
|
||||||
|
/// (0: wakeup event on Z-axis not detected; 1: wakeup event on Z-axis detected)
|
||||||
|
pub wake_up_event_z: RegisterBits<1, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WakeUpSrc {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::WAKE_UP_SRC.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// pub fn get_irq_sources(&self) -> Vec<IrqSource> {
|
||||||
|
// let mut v = Vec::new();
|
||||||
|
// if self.free_fall_event.value() != 0 {
|
||||||
|
// v.push(IrqSource::FreeFall);
|
||||||
|
// }
|
||||||
|
// if self.sleep_event.value() != 0 {
|
||||||
|
// v.push(IrqSource::Sleep);
|
||||||
|
// }
|
||||||
|
// if self.wake_up_event.value() != 0 {
|
||||||
|
// v.push(IrqSource::WakeUp);
|
||||||
|
// }
|
||||||
|
// if self.wake_up_event_x.value() != 0 {
|
||||||
|
// v.push(IrqSource::WakeUpOnX);
|
||||||
|
// }
|
||||||
|
// if self.wake_up_event_y.value() != 0 {
|
||||||
|
// v.push(IrqSource::WakeUpOnY);
|
||||||
|
// }
|
||||||
|
// if self.wake_up_event_z.value() != 0 {
|
||||||
|
// v.push(IrqSource::WakeUpOnZ);
|
||||||
|
// }
|
||||||
|
// v
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for WakeUpSrc {
|
||||||
|
fn from(value: u8) -> Self {
|
||||||
|
let mut s = Self::default();
|
||||||
|
s.free_fall_event.set_from_reg(value);
|
||||||
|
s.sleep_event.set_from_reg(value);
|
||||||
|
s.wake_up_event.set_from_reg(value);
|
||||||
|
s.wake_up_event_x.set_from_reg(value);
|
||||||
|
s.wake_up_event_y.set_from_reg(value);
|
||||||
|
s.wake_up_event_z.set_from_reg(value);
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
32
tflite_demo/lsm6ds3tr/registers/wake_up_ths.rs
Normal file
32
tflite_demo/lsm6ds3tr/registers/wake_up_ths.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//! Single and double-tap function threshold register (r/w).
|
||||||
|
|
||||||
|
use crate::lsm6ds3tr::{RegisterAddress, RegisterBits, RegisterConfig, RegisterValue};
|
||||||
|
|
||||||
|
/// Single and double-tap function threshold register (r/w).
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WakeUpThs {
|
||||||
|
/// Single/double-tap event enable. Default: 0
|
||||||
|
/// (0: only single-tap event enabled;
|
||||||
|
/// 1: both single and double-tap events enabled)
|
||||||
|
pub single_double_tap_enabled: RegisterBits<1, 7>,
|
||||||
|
/// Threshold for wakeup. Default value: 000000
|
||||||
|
/// 1 LSb corresponds to FS_XL/2^6
|
||||||
|
pub wake_up_threshold: RegisterBits<6, 0>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WakeUpThs {
|
||||||
|
pub fn address(&self) -> u8 {
|
||||||
|
RegisterAddress::WAKE_UP_THS.address()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn value(&self) -> u8 {
|
||||||
|
self.single_double_tap_enabled.shifted() | self.wake_up_threshold.shifted()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
RegisterConfig {
|
||||||
|
address: self.address(),
|
||||||
|
value: self.value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
37
tflite_demo/lsm6ds3tr/settings/accel.rs
Normal file
37
tflite_demo/lsm6ds3tr/settings/accel.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use crate::lsm6ds3tr::registers::Ctrl1Xl;
|
||||||
|
use crate::lsm6ds3tr::{AccelSampleRate, AccelScale, RegisterConfig};
|
||||||
|
|
||||||
|
/// Accelerometer settings
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct AccelSettings {
|
||||||
|
pub sample_rate: AccelSampleRate,
|
||||||
|
pub scale: AccelScale,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccelSettings {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
.with_sample_rate(AccelSampleRate::_416Hz)
|
||||||
|
.with_scale(AccelScale::_2G)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_sample_rate(mut self, sample_rate: AccelSampleRate) -> Self {
|
||||||
|
self.sample_rate = sample_rate;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_scale(mut self, scale: AccelScale) -> Self {
|
||||||
|
self.scale = scale;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns accelerometer-related register config to be written
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
Ctrl1Xl {
|
||||||
|
sample_rate: self.sample_rate,
|
||||||
|
scale: self.scale,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.config()
|
||||||
|
}
|
||||||
|
}
|
36
tflite_demo/lsm6ds3tr/settings/gyro.rs
Normal file
36
tflite_demo/lsm6ds3tr/settings/gyro.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use crate::lsm6ds3tr::registers::Ctrl2G;
|
||||||
|
use crate::lsm6ds3tr::{GyroSampleRate, GyroScale, RegisterConfig};
|
||||||
|
|
||||||
|
/// Gyroscope settings
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct GyroSettings {
|
||||||
|
pub scale: GyroScale,
|
||||||
|
pub sample_rate: GyroSampleRate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GyroSettings {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
.with_sample_rate(GyroSampleRate::_416Hz)
|
||||||
|
.with_scale(GyroScale::_250DPS)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_sample_rate(mut self, sample_rate: GyroSampleRate) -> Self {
|
||||||
|
self.sample_rate = sample_rate;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_scale(mut self, scale: GyroScale) -> Self {
|
||||||
|
self.scale = scale;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns gyroscope-related register config to be written
|
||||||
|
pub fn config(&self) -> RegisterConfig {
|
||||||
|
Ctrl2G {
|
||||||
|
sample_rate: self.sample_rate,
|
||||||
|
scale: self.scale,
|
||||||
|
}
|
||||||
|
.config()
|
||||||
|
}
|
||||||
|
}
|
277
tflite_demo/lsm6ds3tr/settings/irq.rs
Normal file
277
tflite_demo/lsm6ds3tr/settings/irq.rs
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
use {
|
||||||
|
crate::lsm6ds3tr::data::XYZ,
|
||||||
|
crate::lsm6ds3tr::registers::{
|
||||||
|
FreeFall, FreeFallThreshold, Int1Ctrl, Int2Ctrl, IntDur2, Md1Cfg, Md2Cfg, RegisterConfig,
|
||||||
|
TapCfg, TapThs6d, WakeUpDur, WakeUpThs,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Interrupt pin/pad routing selection
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub enum InterruptRoute {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
Int1,
|
||||||
|
Int2,
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub enum TapRecognitionMode {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
Single,
|
||||||
|
Double,
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
pub struct FreeFallIrqSettings {
|
||||||
|
pub interrupt_route: InterruptRoute,
|
||||||
|
pub threshold: FreeFallThreshold,
|
||||||
|
pub duration_samples: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WakeUpIrqSettings {
|
||||||
|
pub interrupt_route: InterruptRoute,
|
||||||
|
pub threshold: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct OrientationDetectionIrqSettings {
|
||||||
|
pub interrupt_route: InterruptRoute,
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct TapIrqSettings {
|
||||||
|
pub interrupt_route: InterruptRoute,
|
||||||
|
pub recognition_mode: TapRecognitionMode,
|
||||||
|
pub direction_enable: XYZ<bool>,
|
||||||
|
pub threshold: u8,
|
||||||
|
pub shock_samples: u8,
|
||||||
|
pub quiet_samples: u8,
|
||||||
|
pub duration_samples: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ActivityIrqSettings {
|
||||||
|
pub interrupt_route: InterruptRoute,
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interrupt settings
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct IrqSettings {
|
||||||
|
pub free_fall: FreeFallIrqSettings,
|
||||||
|
pub wake_up: WakeUpIrqSettings,
|
||||||
|
pub orientation_detection: OrientationDetectionIrqSettings,
|
||||||
|
pub tap: TapIrqSettings,
|
||||||
|
pub activity: ActivityIrqSettings,
|
||||||
|
registers: IrqRegisters,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct IrqRegisters {
|
||||||
|
int1_ctrl: Int1Ctrl,
|
||||||
|
int2_ctrl: Int2Ctrl,
|
||||||
|
md1_cfg: Md1Cfg,
|
||||||
|
md2_cfg: Md2Cfg,
|
||||||
|
tap_cfg: TapCfg,
|
||||||
|
tap_ths_6d: TapThs6d,
|
||||||
|
free_fall: FreeFall,
|
||||||
|
wake_up_dur: WakeUpDur,
|
||||||
|
wake_up_ths: WakeUpThs,
|
||||||
|
int_dur2: IntDur2,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IrqSettings {
|
||||||
|
/// Enables Free Fall interrupt
|
||||||
|
pub fn enable_free_fall_irq(
|
||||||
|
&mut self,
|
||||||
|
threshold: FreeFallThreshold,
|
||||||
|
duration_samples: u8,
|
||||||
|
interrupt_route: InterruptRoute,
|
||||||
|
latched_irq: bool,
|
||||||
|
) {
|
||||||
|
self.enable_irqs(latched_irq);
|
||||||
|
|
||||||
|
self.free_fall.threshold = threshold;
|
||||||
|
self.free_fall.duration_samples = duration_samples;
|
||||||
|
self.free_fall.interrupt_route = interrupt_route;
|
||||||
|
|
||||||
|
self.update_registers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables Wake Up interrupt
|
||||||
|
pub fn enable_wake_up_irq(
|
||||||
|
&mut self,
|
||||||
|
threshold: u8,
|
||||||
|
interrupt_route: InterruptRoute,
|
||||||
|
latched_irq: bool,
|
||||||
|
) {
|
||||||
|
self.enable_irqs(latched_irq);
|
||||||
|
|
||||||
|
self.wake_up.threshold = threshold;
|
||||||
|
self.wake_up.interrupt_route = interrupt_route;
|
||||||
|
|
||||||
|
self.update_registers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO provide helper function calculating desired tap time to register values
|
||||||
|
/// Enables Single/Double Tap interrupt
|
||||||
|
pub fn enable_tap_irq(
|
||||||
|
&mut self,
|
||||||
|
recognition_mode: TapRecognitionMode,
|
||||||
|
direction_enable: XYZ<bool>,
|
||||||
|
// threshold: u8,
|
||||||
|
// shock_samples: u8,
|
||||||
|
// quiet_samples: u8,
|
||||||
|
// duration_samples: u8,
|
||||||
|
interrupt_route: InterruptRoute,
|
||||||
|
latched_irq: bool,
|
||||||
|
) {
|
||||||
|
self.enable_irqs(latched_irq);
|
||||||
|
|
||||||
|
self.tap.recognition_mode = recognition_mode;
|
||||||
|
self.tap.direction_enable = direction_enable;
|
||||||
|
// self.tap.threshold = threshold;
|
||||||
|
// self.tap.shock_samples = shock_samples;
|
||||||
|
// self.tap.quiet_samples = quiet_samples;
|
||||||
|
// self.tap.duration_samples = duration_samples;
|
||||||
|
self.tap.interrupt_route = interrupt_route;
|
||||||
|
|
||||||
|
self.update_registers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Enables basic interrupts
|
||||||
|
pub fn enable_irqs(&mut self, latched_irq: bool) {
|
||||||
|
self.registers.tap_cfg.enable_basic_interrupts = 1.into();
|
||||||
|
self.registers.tap_cfg.latched_interrupt = latched_irq.into();
|
||||||
|
|
||||||
|
self.update_registers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disables basic interrupts
|
||||||
|
pub fn disable_irqs(&mut self) {
|
||||||
|
self.registers.tap_cfg.enable_basic_interrupts = 0.into();
|
||||||
|
|
||||||
|
self.update_registers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns interrupt-related registers configs to be written
|
||||||
|
pub fn configs(&self) -> [RegisterConfig; 10] {
|
||||||
|
[
|
||||||
|
self.registers.int1_ctrl.config(),
|
||||||
|
self.registers.int2_ctrl.config(),
|
||||||
|
self.registers.int_dur2.config(),
|
||||||
|
self.registers.md1_cfg.config(),
|
||||||
|
self.registers.md2_cfg.config(),
|
||||||
|
self.registers.tap_cfg.config(),
|
||||||
|
self.registers.tap_ths_6d.config(),
|
||||||
|
self.registers.free_fall.config(),
|
||||||
|
self.registers.wake_up_dur.config(),
|
||||||
|
self.registers.wake_up_ths.config(),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_registers(&mut self) {
|
||||||
|
self.update_free_fall_registers();
|
||||||
|
self.update_wake_up_registers();
|
||||||
|
self.update_tap_registers();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_free_fall_registers(&mut self) {
|
||||||
|
(
|
||||||
|
self.registers.md1_cfg.free_fall_event,
|
||||||
|
self.registers.md2_cfg.free_fall_event,
|
||||||
|
) = match self.free_fall.interrupt_route {
|
||||||
|
InterruptRoute::None => (0.into(), 0.into()),
|
||||||
|
InterruptRoute::Int1 => (1.into(), 0.into()),
|
||||||
|
InterruptRoute::Int2 => (0.into(), 1.into()),
|
||||||
|
InterruptRoute::Both => (1.into(), 1.into()),
|
||||||
|
};
|
||||||
|
self.registers.free_fall.threshold = self.free_fall.threshold;
|
||||||
|
self.registers.wake_up_dur.free_fall_duration_event =
|
||||||
|
(((self.free_fall.threshold as u8) >> 5) & 0b1).into();
|
||||||
|
self.registers.free_fall.duration_event = self.free_fall.duration_samples.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_wake_up_registers(&mut self) {
|
||||||
|
(
|
||||||
|
self.registers.md1_cfg.wake_up_event,
|
||||||
|
self.registers.md2_cfg.wake_up_event,
|
||||||
|
) = match self.wake_up.interrupt_route {
|
||||||
|
InterruptRoute::None => (0.into(), 0.into()),
|
||||||
|
InterruptRoute::Int1 => (1.into(), 0.into()),
|
||||||
|
InterruptRoute::Int2 => (0.into(), 1.into()),
|
||||||
|
InterruptRoute::Both => (1.into(), 1.into()),
|
||||||
|
};
|
||||||
|
self.registers.wake_up_ths.wake_up_threshold = self.wake_up.threshold.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_tap_registers(&mut self) {
|
||||||
|
match self.tap.recognition_mode {
|
||||||
|
TapRecognitionMode::None | TapRecognitionMode::Single => {
|
||||||
|
self.registers.wake_up_ths.single_double_tap_enabled = 0.into()
|
||||||
|
}
|
||||||
|
TapRecognitionMode::Double | TapRecognitionMode::Both => {
|
||||||
|
self.registers.wake_up_ths.single_double_tap_enabled = 1.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match self.tap.recognition_mode {
|
||||||
|
TapRecognitionMode::None => {
|
||||||
|
self.registers.tap_cfg.enable_basic_interrupts = false.into()
|
||||||
|
}
|
||||||
|
TapRecognitionMode::Single => {
|
||||||
|
self.registers.tap_cfg.enable_basic_interrupts = true.into();
|
||||||
|
self.update_single_tap_registers()
|
||||||
|
}
|
||||||
|
TapRecognitionMode::Double => {
|
||||||
|
self.registers.tap_cfg.enable_basic_interrupts = true.into();
|
||||||
|
self.update_double_tap_registers()
|
||||||
|
}
|
||||||
|
TapRecognitionMode::Both => {
|
||||||
|
self.registers.tap_cfg.enable_basic_interrupts = true.into();
|
||||||
|
self.update_single_tap_registers();
|
||||||
|
self.update_double_tap_registers();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.registers.tap_cfg.enable_basic_interrupts = 1.into();
|
||||||
|
self.registers.tap_cfg.enable_x_direction_tap_recognition =
|
||||||
|
self.tap.direction_enable.x.into();
|
||||||
|
self.registers.tap_cfg.enable_y_direction_tap_recognition =
|
||||||
|
self.tap.direction_enable.y.into();
|
||||||
|
self.registers.tap_cfg.enable_z_direction_tap_recognition =
|
||||||
|
self.tap.direction_enable.z.into();
|
||||||
|
self.registers.tap_ths_6d.tap_threshold = self.tap.threshold.into();
|
||||||
|
self.registers.int_dur2.duration = self.tap.duration_samples.into();
|
||||||
|
self.registers.int_dur2.quiet = self.tap.quiet_samples.into();
|
||||||
|
self.registers.int_dur2.shock = self.tap.shock_samples.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_single_tap_registers(&mut self) {
|
||||||
|
(
|
||||||
|
self.registers.md1_cfg.single_tap_event,
|
||||||
|
self.registers.md2_cfg.single_tap_event,
|
||||||
|
) = match self.tap.interrupt_route {
|
||||||
|
InterruptRoute::None => (0.into(), 0.into()),
|
||||||
|
InterruptRoute::Int1 => (1.into(), 0.into()),
|
||||||
|
InterruptRoute::Int2 => (0.into(), 1.into()),
|
||||||
|
InterruptRoute::Both => (1.into(), 1.into()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_double_tap_registers(&mut self) {
|
||||||
|
(
|
||||||
|
self.registers.md1_cfg.double_tap_event,
|
||||||
|
self.registers.md2_cfg.double_tap_event,
|
||||||
|
) = match self.tap.interrupt_route {
|
||||||
|
InterruptRoute::None => (0.into(), 0.into()),
|
||||||
|
InterruptRoute::Int1 => (1.into(), 0.into()),
|
||||||
|
InterruptRoute::Int2 => (0.into(), 1.into()),
|
||||||
|
InterruptRoute::Both => (1.into(), 1.into()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
44
tflite_demo/lsm6ds3tr/settings/mod.rs
Normal file
44
tflite_demo/lsm6ds3tr/settings/mod.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
pub mod accel;
|
||||||
|
pub mod gyro;
|
||||||
|
pub mod irq;
|
||||||
|
|
||||||
|
pub use accel::*;
|
||||||
|
pub use gyro::*;
|
||||||
|
pub use irq::*;
|
||||||
|
|
||||||
|
/// Device settings
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LsmSettings {
|
||||||
|
pub accel: AccelSettings,
|
||||||
|
pub gyro: GyroSettings,
|
||||||
|
pub irq: IrqSettings,
|
||||||
|
pub low_performance_mode: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LsmSettings {
|
||||||
|
pub fn basic() -> Self {
|
||||||
|
Self::default()
|
||||||
|
.with_accel(AccelSettings::new())
|
||||||
|
.with_gyro(GyroSettings::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_accel(mut self, accel_settings: AccelSettings) -> Self {
|
||||||
|
self.accel = accel_settings;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_gyro(mut self, gyro_settings: GyroSettings) -> Self {
|
||||||
|
self.gyro = gyro_settings;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_irq(mut self, irq_settings: IrqSettings) -> Self {
|
||||||
|
self.irq = irq_settings;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_low_performance_mode(mut self) -> Self {
|
||||||
|
self.low_performance_mode = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
658
tflite_demo/src/lsm6ds.rs
Normal file
658
tflite_demo/src/lsm6ds.rs
Normal file
@ -0,0 +1,658 @@
|
|||||||
|
//
|
||||||
|
// lsm6ds3tr
|
||||||
|
//
|
||||||
|
use core::convert::TryFrom;
|
||||||
|
use embedded_hal::i2c::{ErrorKind, ErrorType};
|
||||||
|
|
||||||
|
use crate::lsm6ds::Error::CommunicationError;
|
||||||
|
use embedded_hal_async::i2c::I2c;
|
||||||
|
// use log::info;
|
||||||
|
|
||||||
|
/// Enum containing all possible types of errors when interacting with the IMU
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
CommunicationError,
|
||||||
|
ChipDetectFailed,
|
||||||
|
RegisterReadFailed,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value of the WHO_AM_I register
|
||||||
|
const CHIP_ID: u8 = 0x6a;
|
||||||
|
|
||||||
|
// Earth gravity constant for acceleration conversion
|
||||||
|
const EARTH_GRAVITY: f32 = 9.80665;
|
||||||
|
|
||||||
|
/// 6-DoF IMU accelerometer + gyro
|
||||||
|
pub struct Lsm6ds33<I2C> {
|
||||||
|
i2c: I2C,
|
||||||
|
addr: u8,
|
||||||
|
accelerometer_scale: Option<AccelerometerScale>,
|
||||||
|
gyroscope_scale: Option<GyroscopeFullScale>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I2C, I2cError> Lsm6ds33<I2C>
|
||||||
|
where
|
||||||
|
I2C: I2c<Error = I2cError>,
|
||||||
|
{
|
||||||
|
/// Create an instance of the Lsm6ds33 driver
|
||||||
|
/// If the device cannot be detected on the bus, an error will be returned
|
||||||
|
pub async fn new(i2c: I2C, addr: u8) -> Result<Self, (I2C, Error)> {
|
||||||
|
let mut lsm = Lsm6ds33 {
|
||||||
|
i2c,
|
||||||
|
addr,
|
||||||
|
accelerometer_scale: None,
|
||||||
|
gyroscope_scale: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
match lsm.check().await {
|
||||||
|
Ok(true) => match lsm.set_auto_increment(true).await {
|
||||||
|
Ok(()) => Ok(lsm),
|
||||||
|
Err(e) => Err((lsm.release(), e)),
|
||||||
|
},
|
||||||
|
Ok(false) => Err((lsm.release(), Error::ChipDetectFailed)),
|
||||||
|
Err(e) => Err((lsm.release(), e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the accelerometer output rate
|
||||||
|
pub async fn set_accelerometer_output(
|
||||||
|
&mut self,
|
||||||
|
output: AccelerometerOutput,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.write_register_option(Register::Ctrl1XL, output).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the accelerometer operating range
|
||||||
|
pub async fn set_accelerometer_scale(
|
||||||
|
&mut self,
|
||||||
|
scale: AccelerometerScale,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
match self.write_register_option(Register::Ctrl1XL, scale).await {
|
||||||
|
Ok(()) => {
|
||||||
|
self.accelerometer_scale = Some(scale);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
self.accelerometer_scale = None;
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the accelerometer bandwidth filter
|
||||||
|
pub async fn set_accelerometer_bandwidth(
|
||||||
|
&mut self,
|
||||||
|
bandwidth: AccelerometerBandwidth,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.write_register_option(Register::Ctrl1XL, bandwidth)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the gyroscope output rate
|
||||||
|
pub async fn set_gyroscope_output(&mut self, output: GyroscopeOutput) -> Result<(), Error> {
|
||||||
|
self.write_register_option(Register::Ctrl2G, output).await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the gyroscope operating range
|
||||||
|
pub async fn set_gyroscope_scale(&mut self, scale: GyroscopeFullScale) -> Result<(), Error> {
|
||||||
|
match self.write_register_option(Register::Ctrl2G, scale).await {
|
||||||
|
Ok(()) => {
|
||||||
|
self.gyroscope_scale = Some(scale);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
self.accelerometer_scale = None;
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the low power mode
|
||||||
|
pub async fn set_low_power_mode(&mut self, low_power: bool) -> Result<(), Error> {
|
||||||
|
// N.B. "1" means low-power, "0" means high-performance.
|
||||||
|
self.write_bit(
|
||||||
|
Register::Ctrl6C,
|
||||||
|
low_power as u8,
|
||||||
|
Ctrl6C::AccelHighPerformanceMode as u8,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
self.write_bit(
|
||||||
|
Register::Ctrl7G,
|
||||||
|
low_power as u8,
|
||||||
|
Ctrl7G::HighPerformanceMode as u8,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the gyroscope data for each axis (RAD/s)
|
||||||
|
pub async fn read_gyro(&mut self) -> Result<(f32, f32, f32), Error> {
|
||||||
|
let scale = self.read_gyroscope_scale().await?;
|
||||||
|
self.read_registers(Register::OutXLG)
|
||||||
|
.await
|
||||||
|
.map(|res| Self::convert_gyro_data(&res, scale))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_gyro_data(data: &[u8; 6], scale: GyroscopeFullScale) -> (f32, f32, f32) {
|
||||||
|
// Convert raw data to float
|
||||||
|
let (x, y, z) = Self::u8_to_f32(data);
|
||||||
|
let scale = scale.scale();
|
||||||
|
// Convert to RAD/s (Raw gyro data is in milli-degrees per second per bit)
|
||||||
|
(
|
||||||
|
(x * scale / 1000.0).to_radians(),
|
||||||
|
(y * scale / 1000.0).to_radians(),
|
||||||
|
(z * scale / 1000.0).to_radians(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the accelerometer data for each axis (m/s^2)
|
||||||
|
pub async fn read_accelerometer(&mut self) -> Result<(f32, f32, f32), Error> {
|
||||||
|
let scale = self.read_accelerometer_scale().await?;
|
||||||
|
self.read_registers(Register::OutXLXL)
|
||||||
|
.await
|
||||||
|
.map(|res| Self::convert_accel_data(&res, scale))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_accel_data(data: &[u8; 6], scale: AccelerometerScale) -> (f32, f32, f32) {
|
||||||
|
// Convert raw values to float
|
||||||
|
let (x, y, z) = Self::u8_to_f32(data);
|
||||||
|
let scale = scale.scale();
|
||||||
|
|
||||||
|
// Convert to m/s^2 (Raw value is in mg/bit)
|
||||||
|
(
|
||||||
|
(x * scale / 1000.0) * EARTH_GRAVITY,
|
||||||
|
(y * scale / 1000.0) * EARTH_GRAVITY,
|
||||||
|
(z * scale / 1000.0) * EARTH_GRAVITY,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the temperature (degC)
|
||||||
|
pub async fn read_temperature(&mut self) -> Result<f32, Error> {
|
||||||
|
let data = self.read_registers::<2>(Register::OutTempL).await?;
|
||||||
|
Ok(Self::convert_temp_data(&data))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_temp_data(data: &[u8; 2]) -> f32 {
|
||||||
|
let (lo, hi) = (data[0], data[1]);
|
||||||
|
// Raw temperature as signal 16-bit number
|
||||||
|
let temperature = ((hi as i16) << 8) | (lo as i16);
|
||||||
|
|
||||||
|
// info!("Temperature: {:x} {:x}", hi, lo);
|
||||||
|
// info!("Temperature: {:x}", temperature);
|
||||||
|
|
||||||
|
// As float
|
||||||
|
let temperature = temperature as f32;
|
||||||
|
|
||||||
|
// Converted given the temperature sensitively value 16 bits per C
|
||||||
|
let temperature = (temperature / 256.0) + 25.0;
|
||||||
|
|
||||||
|
temperature
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if there is new accelerometer data
|
||||||
|
pub async fn accel_data_available(&mut self) -> Result<bool, Error> {
|
||||||
|
self.read_status().await.map(|status| status & 0b1 != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if there is new gyro scope data
|
||||||
|
pub async fn gyro_data_available(&mut self) -> Result<bool, Error> {
|
||||||
|
self.read_status().await.map(|status| status & 0b10 != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the accelerometer scale value from the configuration register
|
||||||
|
pub async fn read_accelerometer_scale(&mut self) -> Result<AccelerometerScale, Error> {
|
||||||
|
match self.accelerometer_scale {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => {
|
||||||
|
let scale = self.read_register_option(Register::Ctrl1XL).await?;
|
||||||
|
self.accelerometer_scale = Some(scale);
|
||||||
|
Ok(scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the gyroscope scale value from the configuration register
|
||||||
|
pub async fn read_gyroscope_scale(&mut self) -> Result<GyroscopeFullScale, Error> {
|
||||||
|
match self.gyroscope_scale {
|
||||||
|
Some(v) => Ok(v),
|
||||||
|
None => {
|
||||||
|
let scale = self.read_register_option(Register::Ctrl2G).await?;
|
||||||
|
self.gyroscope_scale = Some(scale);
|
||||||
|
Ok(scale)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn check(&mut self) -> Result<bool, Error> {
|
||||||
|
self.read_register(Register::WhoAmI).await.map(|chip_id| {
|
||||||
|
// info!("Chip ID: {:x}", chip_id);
|
||||||
|
return chip_id == CHIP_ID;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn set_auto_increment(&mut self, enabled: bool) -> Result<(), Error> {
|
||||||
|
self.write_bit(Register::Ctrl3C, enabled as u8, Ctrl3C::AutoIncrement as u8)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_status(&mut self) -> Result<u8, Error> {
|
||||||
|
self.read_register(Register::StatusReg).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_register_option<RO: RegisterOption>(
|
||||||
|
&mut self,
|
||||||
|
register: Register,
|
||||||
|
ro: RO,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.write_bits(register, ro.value(), RO::mask(), RO::bit_offset())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_register_option<RO: RegisterOption + TryFrom<u8>>(
|
||||||
|
&mut self,
|
||||||
|
register: Register,
|
||||||
|
) -> Result<RO, Error> {
|
||||||
|
let value = self.read_register(register).await?;
|
||||||
|
RO::try_from(value).map_err(|_| Error::RegisterReadFailed)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_bit(&mut self, register: Register, value: u8, shift: u8) -> Result<(), Error> {
|
||||||
|
self.write_bits(register, value, 0x01, shift).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_bits(
|
||||||
|
&mut self,
|
||||||
|
register: Register,
|
||||||
|
new_value: u8,
|
||||||
|
mask: u8,
|
||||||
|
shift: u8,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let current_value = self.read_register(register).await?;
|
||||||
|
let modified_value = (current_value & !(mask << shift)) | ((new_value & mask) << shift);
|
||||||
|
self.write_register(register, modified_value).await
|
||||||
|
}
|
||||||
|
|
||||||
|
fn u8_to_f32(res: &[u8; 6]) -> (f32, f32, f32) {
|
||||||
|
let (x, y, z) = (
|
||||||
|
(res[0] as i16) | ((res[1] as i16) << 8),
|
||||||
|
(res[2] as i16) | ((res[3] as i16) << 8),
|
||||||
|
(res[4] as i16) | ((res[5] as i16) << 8),
|
||||||
|
);
|
||||||
|
(x as f32, y as f32, z as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read a byte from the given register
|
||||||
|
async fn read_register(&mut self, register: Register) -> Result<u8, Error> {
|
||||||
|
let mut res = [0u8];
|
||||||
|
if self
|
||||||
|
.i2c
|
||||||
|
.write_read(self.addr, &[register.into()], &mut res)
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Ok(res[0])
|
||||||
|
} else {
|
||||||
|
Err(CommunicationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_registers<const N: usize>(
|
||||||
|
&mut self,
|
||||||
|
start_reg: Register,
|
||||||
|
) -> Result<[u8; N], Error> {
|
||||||
|
let mut res = [0u8; N];
|
||||||
|
if self
|
||||||
|
.i2c
|
||||||
|
.write_read(self.addr, &[start_reg.into()], &mut res)
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Ok(res)
|
||||||
|
} else {
|
||||||
|
Err(CommunicationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the specified value to the given register
|
||||||
|
async fn write_register(&mut self, register: Register, value: u8) -> Result<(), Error> {
|
||||||
|
if self
|
||||||
|
.i2c
|
||||||
|
.write(self.addr, &[register.into(), value])
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(CommunicationError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the underlying I2C device
|
||||||
|
pub fn release(self) -> I2C {
|
||||||
|
self.i2c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RegisterError {
|
||||||
|
ConversionError,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device registers
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Register {
|
||||||
|
FifoCtrl1 = 0x06,
|
||||||
|
FifoCtrl2 = 0x07,
|
||||||
|
FifoCtrl3 = 0x08,
|
||||||
|
FifoCtrl4 = 0x09,
|
||||||
|
FifoCtrl5 = 0x0A,
|
||||||
|
|
||||||
|
OrientCfgG = 0x0B,
|
||||||
|
|
||||||
|
Int1Ctrl = 0x0D,
|
||||||
|
Int2Ctrl = 0x0E,
|
||||||
|
|
||||||
|
WhoAmI = 0x0F,
|
||||||
|
|
||||||
|
Ctrl1XL = 0x10,
|
||||||
|
Ctrl2G = 0x11,
|
||||||
|
Ctrl3C = 0x12,
|
||||||
|
Ctrl4C = 0x13,
|
||||||
|
Ctrl5C = 0x14,
|
||||||
|
Ctrl6C = 0x15,
|
||||||
|
Ctrl7G = 0x16,
|
||||||
|
Ctrl8Xl = 0x18,
|
||||||
|
Ctrl10C = 0x19,
|
||||||
|
|
||||||
|
WakeUpSrc = 0x1B,
|
||||||
|
TapSrc = 0x1C,
|
||||||
|
D6dSrc = 0x1D,
|
||||||
|
|
||||||
|
StatusReg = 0x1E,
|
||||||
|
|
||||||
|
OutTempL = 0x20,
|
||||||
|
OutTempH = 0x21,
|
||||||
|
|
||||||
|
OutXLG = 0x22,
|
||||||
|
OutXHG = 0x23,
|
||||||
|
OutYLG = 0x24,
|
||||||
|
OutYHG = 0x25,
|
||||||
|
OutZLG = 0x26,
|
||||||
|
OutZHG = 0x27,
|
||||||
|
OutXLXL = 0x28,
|
||||||
|
OutXHXL = 0x29,
|
||||||
|
OutYLXL = 0x2A,
|
||||||
|
OutYHXL = 0x2B,
|
||||||
|
OutZLXL = 0x2C,
|
||||||
|
OutZHXL = 0x2D,
|
||||||
|
|
||||||
|
FifoStatus1 = 0x3A,
|
||||||
|
FifoStatus2 = 0x3B,
|
||||||
|
FifoStatus3 = 0x3C,
|
||||||
|
FifoStatus4 = 0x3D,
|
||||||
|
|
||||||
|
FifoDataOutL = 0x3E,
|
||||||
|
FifoDataOutH = 0x3F,
|
||||||
|
|
||||||
|
Timestamp1Reg = 0x41,
|
||||||
|
Timestamp2Reg = 0x42,
|
||||||
|
|
||||||
|
StepTimestampL = 0x49,
|
||||||
|
StepTimestampH = 0x4A,
|
||||||
|
|
||||||
|
StepCounterL = 0x4B,
|
||||||
|
StepCounterH = 0x4C,
|
||||||
|
|
||||||
|
FuncSrc = 0x53,
|
||||||
|
|
||||||
|
TapCfg = 0x58,
|
||||||
|
TapThs6d = 0x59,
|
||||||
|
|
||||||
|
IntDur2 = 0x5A,
|
||||||
|
|
||||||
|
WakeUpThs = 0x5B,
|
||||||
|
WakeUpDur = 0x5C,
|
||||||
|
|
||||||
|
FreeFall = 0x5D,
|
||||||
|
|
||||||
|
Md1Cfg = 0x5E,
|
||||||
|
Md2Cfg = 0x5F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Register> for u8 {
|
||||||
|
fn from(r: Register) -> u8 {
|
||||||
|
r as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait RegisterOption {
|
||||||
|
fn value(&self) -> u8;
|
||||||
|
fn bit_offset() -> u8;
|
||||||
|
fn mask() -> u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// --- CTRL1_XL --------------------------------------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum AccelerometerOutput {
|
||||||
|
PowerDown = 0b0000,
|
||||||
|
Rate13 = 0b0001,
|
||||||
|
Rate26 = 0b0010,
|
||||||
|
Rate52 = 0b0011,
|
||||||
|
Rate104 = 0b0100,
|
||||||
|
Rate208 = 0b0101,
|
||||||
|
Rate416 = 0b0110,
|
||||||
|
Rate833 = 0b0111,
|
||||||
|
Rate1_66k = 0b1000,
|
||||||
|
Rate3_33k = 0b1001,
|
||||||
|
Rate6_66k = 0b1010,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterOption for AccelerometerOutput {
|
||||||
|
fn value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
fn mask() -> u8 {
|
||||||
|
0xF
|
||||||
|
}
|
||||||
|
fn bit_offset() -> u8 {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Accelerometer full-scale selection
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum AccelerometerScale {
|
||||||
|
G02 = 0b00,
|
||||||
|
G16 = 0b01,
|
||||||
|
G04 = 0b10,
|
||||||
|
G08 = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterOption for AccelerometerScale {
|
||||||
|
fn value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
fn mask() -> u8 {
|
||||||
|
0x03
|
||||||
|
}
|
||||||
|
fn bit_offset() -> u8 {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AccelerometerScale {
|
||||||
|
pub fn scale(&self) -> f32 {
|
||||||
|
match *self {
|
||||||
|
Self::G02 => 0.061,
|
||||||
|
Self::G04 => 0.122,
|
||||||
|
Self::G08 => 0.244,
|
||||||
|
Self::G16 => 0.488,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for AccelerometerScale {
|
||||||
|
type Error = RegisterError;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
let value = (value >> Self::bit_offset()) & Self::mask();
|
||||||
|
match value {
|
||||||
|
0b00 => Ok(Self::G02),
|
||||||
|
0b01 => Ok(Self::G16),
|
||||||
|
0b10 => Ok(Self::G04),
|
||||||
|
0b11 => Ok(Self::G08),
|
||||||
|
_ => Err(RegisterError::ConversionError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum AccelerometerBandwidth {
|
||||||
|
Freq400 = 0b00,
|
||||||
|
Freq200 = 0b01,
|
||||||
|
Freq100 = 0b10,
|
||||||
|
Freq50 = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterOption for AccelerometerBandwidth {
|
||||||
|
fn value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
fn mask() -> u8 {
|
||||||
|
0x03
|
||||||
|
}
|
||||||
|
fn bit_offset() -> u8 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
// --- CTRL2_G --------------------------------------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum GyroscopeOutput {
|
||||||
|
PowerDown = 0b0000,
|
||||||
|
Rate13 = 0b0001,
|
||||||
|
Rate26 = 0b0010,
|
||||||
|
Rate52 = 0b0011,
|
||||||
|
Rate104 = 0b0100,
|
||||||
|
Rate208 = 0b0101,
|
||||||
|
Rate416 = 0b0110,
|
||||||
|
Rate833 = 0b0111,
|
||||||
|
Rate1_66k = 0b1000,
|
||||||
|
Rate3_33k = 0b1001,
|
||||||
|
Rate6_66k = 0b1010,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterOption for GyroscopeOutput {
|
||||||
|
fn value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
fn mask() -> u8 {
|
||||||
|
0xF
|
||||||
|
}
|
||||||
|
fn bit_offset() -> u8 {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum GyroscopeFullScale {
|
||||||
|
Dps125 = 0b001,
|
||||||
|
Dps245 = 0b000,
|
||||||
|
Dps500 = 0b010,
|
||||||
|
Dps1000 = 0b100,
|
||||||
|
Dps2000 = 0b110,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterOption for GyroscopeFullScale {
|
||||||
|
fn value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
fn mask() -> u8 {
|
||||||
|
0b111
|
||||||
|
}
|
||||||
|
fn bit_offset() -> u8 {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GyroscopeFullScale {
|
||||||
|
pub fn scale(&self) -> f32 {
|
||||||
|
match *self {
|
||||||
|
Self::Dps125 => 4.375,
|
||||||
|
Self::Dps245 => 8.75,
|
||||||
|
Self::Dps500 => 17.50,
|
||||||
|
Self::Dps1000 => 35.0,
|
||||||
|
Self::Dps2000 => 70.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u8> for GyroscopeFullScale {
|
||||||
|
type Error = RegisterError;
|
||||||
|
|
||||||
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
|
let value = (value >> Self::bit_offset()) & Self::mask();
|
||||||
|
match value {
|
||||||
|
0b001 => Ok(GyroscopeFullScale::Dps125),
|
||||||
|
0b000 => Ok(GyroscopeFullScale::Dps245),
|
||||||
|
0b010 => Ok(GyroscopeFullScale::Dps500),
|
||||||
|
0b100 => Ok(GyroscopeFullScale::Dps1000),
|
||||||
|
0b110 => Ok(GyroscopeFullScale::Dps2000),
|
||||||
|
_ => Err(RegisterError::ConversionError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Debug, Clone, Copy)]
|
||||||
|
// pub enum GyroscopeFullScale125Dps {
|
||||||
|
// Disabled = 0,
|
||||||
|
// Enabled = 1,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl RegisterOption for GyroscopeFullScale125Dps {
|
||||||
|
// fn value(&self) -> u8 {
|
||||||
|
// *self as u8
|
||||||
|
// }
|
||||||
|
// fn mask() -> u8 {
|
||||||
|
// 0b1
|
||||||
|
// }
|
||||||
|
// fn bit_offset() -> u8 {
|
||||||
|
// 1
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn option_mask<T: RegisterOption>(opt: &T) -> u8 {
|
||||||
|
// 0x01 << opt.bit_offset()
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// Bit fields for CTRL3_C
|
||||||
|
pub enum Ctrl3C {
|
||||||
|
Boot = 7,
|
||||||
|
BlockDataUpdate = 6,
|
||||||
|
InterruptActivationLevel = 5,
|
||||||
|
InterruptPadOutput = 4,
|
||||||
|
SpiSerialInterfaceMode = 3,
|
||||||
|
AutoIncrement = 2,
|
||||||
|
Endian = 1,
|
||||||
|
SoftwareReset = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bit fields for CTRL6_C
|
||||||
|
pub enum Ctrl6C {
|
||||||
|
GyroEdgeTrigge = 7,
|
||||||
|
GyroLevelTrigger = 6,
|
||||||
|
GyroLevelLatched = 5,
|
||||||
|
AccelHighPerformanceMode = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Bit fields for CTRL6_G
|
||||||
|
pub enum Ctrl7G {
|
||||||
|
HighPerformanceMode = 7,
|
||||||
|
HighPassFilter = 6,
|
||||||
|
SourceRegisterRounding = 3,
|
||||||
|
}
|
@ -2,16 +2,17 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
mod i2c;
|
mod i2c;
|
||||||
|
mod lsm6ds;
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use embedded_alloc::LlffHeap;
|
use embedded_alloc::LlffHeap;
|
||||||
use libm::sinf;
|
use libm::sinf;
|
||||||
use lsm6ds3tr::{
|
use lsm6ds::Lsm6ds33;
|
||||||
interface::{I2cInterface, SpiInterface},
|
// use lsm6ds3tr::{
|
||||||
LsmSettings, LSM6DS3TR,
|
// interface::{I2cInterface, SpiInterface},
|
||||||
};
|
// LsmSettings, LSM6DS3TR,
|
||||||
|
// };
|
||||||
// use lsm6ds3tr::{interface::SpiInterface, AccelScale, LsmSettings, LSM6DS3TR};
|
// use lsm6ds3tr::{interface::SpiInterface, AccelScale, LsmSettings, LSM6DS3TR};
|
||||||
use microflow::model;
|
use microflow::model;
|
||||||
use nalgebra::matrix;
|
use nalgebra::matrix;
|
||||||
@ -127,17 +128,19 @@ fn main() -> ! {
|
|||||||
// let mut imu = LSM6DS3TR::new(spi_interface);
|
// let mut imu = LSM6DS3TR::new(spi_interface);
|
||||||
// imu.init().expect("Couldn't initialize the LSM6 sensor!");
|
// imu.init().expect("Couldn't initialize the LSM6 sensor!");
|
||||||
|
|
||||||
let scl = port0.p0_27.into_floating_input().degrade();
|
// let scl = port0.p0_27.into_floating_input().degrade();
|
||||||
let sda = port0.p0_07.into_floating_input().degrade();
|
// let sda = port0.p0_07.into_floating_input().degrade();
|
||||||
|
|
||||||
let pins = twim::Pins { scl: scl, sda: sda };
|
// let pins = twim::Pins { scl: scl, sda: sda };
|
||||||
|
|
||||||
let i2c = Twim::new(p.TWIM0, pins, twim::Frequency::K100);
|
// let i2c = Twim::new(p.TWIM0, pins, twim::Frequency::K100);
|
||||||
|
|
||||||
let i2c_interface = I2cInterface::new(i2c);
|
// let i2c_interface = I2cInterface::new(i2c);
|
||||||
|
|
||||||
// let mut imu = LSM6DS3TR::new(I2cInterface::new(""));
|
// let mut imu = LSM6DS3TR::new(I2cInterface::new(""));
|
||||||
|
|
||||||
|
// let mut imu = Lsm6ds33::new(i2c, addr);
|
||||||
|
|
||||||
let rtc = Rtc::new(p.RTC0, 0).unwrap();
|
let rtc = Rtc::new(p.RTC0, 0).unwrap();
|
||||||
rtc.enable_counter();
|
rtc.enable_counter();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user