435 lines
12 KiB
Rust
435 lines
12 KiB
Rust
//! All device constants used in the driver, mostly register addresses.
|
|
//!
|
|
//! NOTE: Earlier revisions of Datasheet and Register Map has way more info about interrupt usage,
|
|
//! particularly rev 3.2
|
|
//!
|
|
//! #### Sources:
|
|
//! * Register map (rev 3.2): https://arduino.ua/docs/RM-MPU-6000A.pdf
|
|
//! * Datasheet (rev 3.2): https://www.cdiweb.com/datasheets/invensense/ps-mpu-6000a.pdf
|
|
|
|
|
|
/// Gyro Sensitivity
|
|
///
|
|
/// Measurements are scaled like this:
|
|
/// x * range/2**(resolution-1) or x / (2**(resolution-1) / range)
|
|
///
|
|
/// Sources:
|
|
/// * https://www.nxp.com/docs/en/application-note/AN3461.pdf
|
|
/// * https://theccontinuum.com/2012/09/24/arduino-imu-pitch-roll-from-accelerometer/
|
|
/// * https://makersportal.com/blog/2019/8/17/arduino-mpu6050-high-frequency-accelerometer-and-gyroscope-data-saver#accel_test
|
|
/// * https://github.com/kriswiner/MPU6050/wiki/2014-Invensense-Developer%27s-Conference
|
|
/// * rust MPU9250 driver on github
|
|
pub const GYRO_SENS: (f32, f32, f32, f32) = (131., 65.5, 32.8, 16.4);
|
|
|
|
/// Accelerometer Sensitivity
|
|
///
|
|
/// Measurements are scaled like this:
|
|
///
|
|
/// x * range/2**(resolution-1) or x / (2**(resolution-1) / range)
|
|
/// Sources:
|
|
/// * https://www.nxp.com/docs/en/application-note/AN3461.pdf
|
|
/// * https://theccontinuum.com/2012/09/24/arduino-imu-pitch-roll-from-accelerometer/
|
|
/// * https://makersportal.com/blog/2019/8/17/arduino-mpu6050-high-frequency-accelerometer-and-gyroscope-data-saver#accel_test
|
|
/// * https://github.com/kriswiner/MPU6050/wiki/2014-Invensense-Developer%27s-Conference
|
|
/// * rust MPU9250 driver on github
|
|
pub const ACCEL_SENS: (f32, f32, f32, f32) = (16384., 8192., 4096., 2048.);
|
|
/// Temperature Offset
|
|
pub const TEMP_OFFSET: f32 = 36.53;
|
|
/// Temperature Sensitivity
|
|
pub const TEMP_SENSITIVITY: f32 = 340.;
|
|
|
|
/// Motion Threshold Register
|
|
pub const MOT_THR: u8 = 0x1F;
|
|
/// Motion Duration Detection Register
|
|
pub const MOT_DUR: u8 = 0x20;
|
|
/// High Byte Register Gyro x orientation
|
|
pub const GYRO_REGX_H: u8 = 0x43;
|
|
/// High Byte Register Gyro y orientation
|
|
pub const GYRO_REGY_H: u8 = 0x45;
|
|
/// High Byte Register Gyro z orientation
|
|
pub const GYRO_REGZ_H: u8 = 0x47;
|
|
/// High Byte Register Calc roll
|
|
pub const ACC_REGX_H : u8= 0x3b;
|
|
/// High Byte Register Calc pitch
|
|
pub const ACC_REGY_H : u8= 0x3d;
|
|
/// High Byte Register Calc yaw
|
|
pub const ACC_REGZ_H : u8= 0x3f;
|
|
/// High Byte Register Temperature
|
|
pub const TEMP_OUT_H : u8= 0x41;
|
|
/// Slave address of Mpu6050
|
|
pub const SLAVE_ADDR: u8 = 0x68;
|
|
/// Internal register to check slave addr
|
|
pub const WHOAMI: u8 = 0x75;
|
|
|
|
/// Describes a bit block from bit number 'bit' to 'bit'+'length'
|
|
pub struct BitBlock {
|
|
pub bit: u8,
|
|
pub length: u8
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 26: Configuration (DLPF, External signal)
|
|
pub struct CONFIG;
|
|
|
|
impl CONFIG {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x1a;
|
|
/// external Frame Synchronisation (FSYNC)
|
|
pub const EXT_SYNC_SET: BitBlock = BitBlock { bit: 5, length: 3};
|
|
/// Digital Low Pass Filter (DLPF) config
|
|
pub const DLPF_CFG: BitBlock = BitBlock { bit: 2, length: 3};
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 27: Gyro Config
|
|
pub struct GYRO_CONFIG;
|
|
|
|
impl GYRO_CONFIG {
|
|
pub const ADDR: u8 = 0x1b;
|
|
/// Gyro x axis self test bit
|
|
pub const XG_ST: u8 = 7;
|
|
/// Gyro y axis self test bit
|
|
pub const YG_ST: u8 = 6;
|
|
/// Gyro z axis self test bit
|
|
pub const ZG_ST: u8 = 5;
|
|
/// Gyro Config FS_SEL
|
|
pub const FS_SEL: BitBlock = BitBlock { bit: 4, length: 2 };
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 28: Accel Config
|
|
pub struct ACCEL_CONFIG;
|
|
|
|
impl ACCEL_CONFIG {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x1c;
|
|
/// Accel x axis self test bit
|
|
pub const XA_ST: u8 = 7;
|
|
/// Accel y axis self test bit
|
|
pub const YA_ST: u8 = 6;
|
|
/// Accel z axis self test bit
|
|
pub const ZA_ST: u8 = 5;
|
|
/// Accel Config FS_SEL
|
|
pub const FS_SEL: BitBlock = BitBlock { bit: 4, length: 2};
|
|
/// Accel Config ACCEL_HPF
|
|
pub const ACCEL_HPF: BitBlock = BitBlock { bit: 2, length: 3};
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 55: INT Pin / Bypass Enable Configuration
|
|
pub struct INT_PIN_CFG;
|
|
|
|
impl INT_PIN_CFG {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x37;
|
|
/// INT pin logic level
|
|
pub const INT_LEVEL: u8 = 7;
|
|
/// INT pin config
|
|
pub const INT_OPEN: u8 = 6;
|
|
/// Pulse (length)
|
|
pub const LATCH_INT_EN: u8 = 5;
|
|
/// INT clear conditions
|
|
pub const INT_RD_CLEAR: u8 = 4;
|
|
/// FSYNC PIN logic level
|
|
pub const FSYNC_INT_LEVEL: u8 = 3;
|
|
/// FSYNC PIN config
|
|
pub const FSYNC_INT_EN: u8 = 2;
|
|
/// i2c access/bypass
|
|
pub const I2C_BYPASS_EN: u8 = 1;
|
|
/// enable/disable reference clock output
|
|
pub const CLKOUT_EN: u8 = 0;
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 56: Interrupt Status
|
|
pub struct INT_ENABLE;
|
|
|
|
impl INT_ENABLE {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x38;
|
|
/// Generate interrupt Free Fall Detection
|
|
pub const FF_EN: u8 = 7;
|
|
/// Generate interrupt with Motion Detected
|
|
pub const MOT_EN: u8 = 6;
|
|
/// Generate iterrrupt when Zero Motion Detection
|
|
pub const ZMOT_EN: u8 = 5;
|
|
/// Generate iterrupt when FIFO buffer overflow
|
|
pub const FIFO_OFLOW_END: u8 = 4;
|
|
/// this bit enables any of the I2C Masterinterrupt sources to generate an interrupt
|
|
pub const I2C_MST_INT_EN: u8 = 3;
|
|
/// enables Data Ready interrupt, each time a write operation to all sensor registers completed
|
|
pub const DATA_RDY_EN: u8 = 0;
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 58: Interrupt Status
|
|
pub struct INT_STATUS;
|
|
|
|
impl INT_STATUS {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x3a;
|
|
/// Free Fall Interrupt
|
|
pub const FF_INT: u8 = 7;
|
|
/// Motion Detection Interrupt
|
|
pub const MOT_INT: u8 = 6;
|
|
/// Zero Motion Detection Interrupt
|
|
pub const ZMOT_INT: u8 = 5;
|
|
/// FIFO buffer overflow
|
|
pub const FIFO_OFLOW_INT: u8 = 4;
|
|
/// i2c master interrupt has been generated
|
|
pub const I2C_MSF_INT: u8 = 3;
|
|
/// Data is ready
|
|
pub const DATA_RDY_INT: u8 = 0;
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 97: Motion Detection Status
|
|
pub struct MOT_DETECT_STATUS;
|
|
|
|
impl MOT_DETECT_STATUS {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x61;
|
|
/// motion in the negative X axis has generated a Motion detection interrupt
|
|
pub const MOT_XNEG: u8 = 7;
|
|
/// motion in the positive X axis has generated a Motion detection interrupt
|
|
pub const MOT_XPOS: u8 = 6;
|
|
/// motion in the negative Y axis has generated a Motion detection interrupt
|
|
pub const MOT_YNEG: u8 = 5;
|
|
/// motion in the positive Y axis has generated a Motion detection interrupt
|
|
pub const MOT_YPOS: u8 = 4;
|
|
/// motion in the negative Z axis has generated a Motion detection interrupt.
|
|
pub const MOT_ZNEG: u8 = 3;
|
|
/// motion in the positive Z axis has generated a Motion detection interrupt
|
|
pub const MOT_ZPOS: u8 = 2;
|
|
/// Zero Motion detection interrupt is generated
|
|
pub const MOT_ZRMOT: u8 = 0;
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 105: Motion Detection Control
|
|
pub struct MOT_DETECT_CONTROL;
|
|
|
|
impl MOT_DETECT_CONTROL {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x69;
|
|
/// Additional delay
|
|
pub const ACCEL_ON_DELAY: BitBlock = BitBlock { bit: 5, length: 2};
|
|
/// Free Fall count
|
|
pub const FF_COUNT: BitBlock = BitBlock { bit: 3, length: 2};
|
|
/// Motion Detection cound
|
|
pub const MOT_COUNT: BitBlock = BitBlock { bit: 1, length: 2};
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 107: Power Management 1
|
|
pub struct PWR_MGMT_1;
|
|
|
|
impl PWR_MGMT_1 {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x6b;
|
|
/// Device Reset bit
|
|
pub const DEVICE_RESET: u8 = 7;
|
|
/// Sleep mode bit (Should be called "Low Power", doesn't actually sleep)
|
|
pub const SLEEP: u8 = 6;
|
|
/// Cycle bit for wake operations
|
|
pub const CYCLE: u8 = 5;
|
|
/// Temperature sensor enable/disable bit
|
|
pub const TEMP_DIS: u8 = 3;
|
|
/// Clock Control
|
|
pub const CLKSEL: BitBlock = BitBlock { bit: 2, length: 3 };
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug)]
|
|
/// Register 107: Power Management 2
|
|
pub struct PWR_MGMT_2;
|
|
|
|
impl PWR_MGMT_2 {
|
|
/// Base Address
|
|
pub const ADDR: u8 = 0x6c;
|
|
/// Wake up frequency
|
|
pub const LP_WAKE_CTRL: BitBlock = BitBlock { bit: 7, length: 2};
|
|
/// disable accel axis x
|
|
pub const STBY_XA: u8 = 5;
|
|
/// disable accel axis y
|
|
pub const STBY_YA: u8 = 4;
|
|
/// disable accel axis z
|
|
pub const STBY_ZA: u8 = 3;
|
|
/// disable gyro axis x
|
|
pub const STBY_XG: u8 = 2;
|
|
/// disable gyro axis y
|
|
pub const STBY_YG: u8 = 1;
|
|
/// disable gyro axis z
|
|
pub const STBY_ZG: u8 = 0;
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
/// Wake values
|
|
pub enum LP_WAKE_CTRL {
|
|
/// 1.25 Hz
|
|
_1P25 = 0,
|
|
/// 2.5 Hz
|
|
_2P5,
|
|
/// 5 Hz
|
|
_5,
|
|
/// 10 Hz
|
|
_10,
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
/// Accelerometer High Pass Filter Values
|
|
pub enum ACCEL_HPF {
|
|
/// Cut off frequency: None
|
|
_RESET = 0,
|
|
/// Cut off frequency: 5 Hz
|
|
_5 = 1,
|
|
/// Cut off frequency: 2.5 Hz
|
|
_2P5 = 2,
|
|
/// Cut off frequency: 1.25 Hz
|
|
_1P25 = 3,
|
|
/// Cut off frequency: 0.63 Hz
|
|
_0P63 = 4,
|
|
/// When triggered, the filter holds the present sample. The filter output will be the
|
|
/// difference between the input sample and the held sample
|
|
_HOLD = 7
|
|
}
|
|
|
|
impl From<u8> for ACCEL_HPF {
|
|
fn from(range: u8) -> Self
|
|
{
|
|
match range {
|
|
0 => ACCEL_HPF::_RESET,
|
|
1 => ACCEL_HPF::_5,
|
|
2 => ACCEL_HPF::_2P5,
|
|
3 => ACCEL_HPF::_1P25,
|
|
4 => ACCEL_HPF::_0P63,
|
|
7 => ACCEL_HPF::_HOLD,
|
|
_ => ACCEL_HPF::_RESET,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
|
/// Clock Source Select Values
|
|
pub enum CLKSEL {
|
|
/// Internal 8MHz oscillator
|
|
OSCILL = 0,
|
|
/// PLL with X axis gyroscope reference
|
|
GXAXIS = 1,
|
|
/// PLL with Y axis gyroscope reference
|
|
GYAXIS = 2,
|
|
/// PLL with Z axis gyroscope reference
|
|
GZAXIS = 3,
|
|
/// PLL with external 32.768kHz reference
|
|
EXT_32p7 = 4,
|
|
/// PLL with external 19.2MHz reference
|
|
EXT_19P2 = 5,
|
|
/// Reserved
|
|
RESERV = 6,
|
|
/// Stops the clock and keeps the timing generator in reset
|
|
STOP = 7,
|
|
}
|
|
|
|
impl From<u8> for CLKSEL {
|
|
fn from(clk: u8) -> Self {
|
|
match clk {
|
|
0 => CLKSEL::OSCILL,
|
|
1 => CLKSEL::GXAXIS,
|
|
2 => CLKSEL::GYAXIS,
|
|
3 => CLKSEL::GZAXIS,
|
|
4 => CLKSEL::EXT_32p7,
|
|
5 => CLKSEL::EXT_19P2,
|
|
6 => CLKSEL::RESERV,
|
|
7 => CLKSEL::STOP,
|
|
_ => CLKSEL::GXAXIS
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Defines accelerometer range/sensivity
|
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
|
pub enum AccelRange {
|
|
/// 2G
|
|
G2 = 0,
|
|
/// 4G
|
|
G4,
|
|
/// 8G
|
|
G8,
|
|
/// 16G
|
|
G16,
|
|
}
|
|
|
|
/// Defines gyro range/sensitivity
|
|
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
|
pub enum GyroRange {
|
|
/// 250 degrees
|
|
D250 = 0,
|
|
/// 500 degrees
|
|
D500,
|
|
/// 1000 degrees
|
|
D1000,
|
|
/// 2000 degrees
|
|
D2000,
|
|
}
|
|
|
|
impl From<u8> for GyroRange {
|
|
fn from(range: u8) -> Self
|
|
{
|
|
match range {
|
|
0 => GyroRange::D250,
|
|
1 => GyroRange::D500,
|
|
2 => GyroRange::D1000,
|
|
3 => GyroRange::D2000,
|
|
_ => GyroRange::D250
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<u8> for AccelRange {
|
|
fn from(range: u8) -> Self
|
|
{
|
|
match range {
|
|
0 => AccelRange::G2,
|
|
1 => AccelRange::G4,
|
|
2 => AccelRange::G8,
|
|
3 => AccelRange::G16,
|
|
_ => AccelRange::G2
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AccelRange {
|
|
// Converts accelerometer range to correction/scaling factor, see register sheet
|
|
pub(crate) fn sensitivity(&self) -> f32 {
|
|
match &self {
|
|
AccelRange::G2 => ACCEL_SENS.0,
|
|
AccelRange::G4 => ACCEL_SENS.1,
|
|
AccelRange::G8 => ACCEL_SENS.2,
|
|
AccelRange::G16 => ACCEL_SENS.3,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl GyroRange {
|
|
// Converts gyro range to correction/scaling factor, see register sheet
|
|
pub(crate) fn sensitivity(&self) -> f32 {
|
|
match &self {
|
|
GyroRange::D250 => GYRO_SENS.0,
|
|
GyroRange::D500 => GYRO_SENS.1,
|
|
GyroRange::D1000 => GYRO_SENS.2,
|
|
GyroRange::D2000 => GYRO_SENS.3,
|
|
}
|
|
}
|
|
}
|