//! All constants used in the driver, mostly register addresses //! Register map: https://arduino.ua/docs/RM-MPU-6000A.pdf //! Datasheet with WAY more info about interrupts (Revision 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.; #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] pub struct Specs; impl Specs { // pub const ACCEL_SELF_TEST_MIN: u8 = -14; pub const ACCEL_SELF_TEST_MAX: u8 = 14; } #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug)] /// Register addresses pub enum Registers { /// High Byte Register Gyro x orientation GYRO_REGX_H = 0x43, /// High Byte Register Gyro y orientation GYRO_REGY_H = 0x45, /// High Byte Register Gyro z orientation GYRO_REGZ_H = 0x47, /// High Byte Register Calc roll ACC_REGX_H = 0x3b, /// High Byte Register Calc pitch ACC_REGY_H = 0x3d, /// High Byte Register Calc yaw ACC_REGZ_H = 0x3f, /// High Byte Register Temperature TEMP_OUT_H = 0x41, // } /// Slave address of Mpu6050 pub const SLAVE_ADDR: u8 = 0x68; /// Internal register to check slave addr pub const WHOAMI: u8 = 0x75; /// Motion Threshold Register pub const MOT_THR: u8 = 0x1F; /// Motion Duration Detection Register pub const MOT_DUR: u8 = 0x20; /// Describes a bit block from bit number 'bit' to 'bit'+'length' pub struct BitBlock { pub bit: u8, pub length: u8 } impl Registers { pub fn addr(&self) -> u8 { *self as 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 { _1P25 = 0, _2P5, _5, _10, } #[allow(non_camel_case_types)] #[derive(Copy, Clone, Debug, Eq, PartialEq)] /// Accelerometer High Pass Filter Values pub enum ACCEL_HPF { _RESET = 0, _5 = 1, _2P5 = 2, _1P25 = 3, _0P63 = 4, _HOLD = 7 } impl From 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 { OSCILL = 0, GXAXIS = 1, GYAXIS = 2, GZAXIS = 3, EXT_32p7 = 4, EXT_19P2 = 5, RESERV = 6, STOP = 7, } impl From 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 } } }