test_code / Mbed OS test_icm20948
Revision:
0:efb1550773f1
Child:
1:8459e28d77a1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/icm20948.h	Fri Mar 19 21:59:25 2021 +0000
@@ -0,0 +1,284 @@
+/*
+ Note: The ICM-20948 is an I2C sensor and uses the Arduino Wire library.
+ */
+#ifndef _ICM20948_H_
+#define _ICM20948_H_
+
+#include <SPI.h>
+#include <Wire.h>
+
+#define SERIAL_DEBUG true
+
+// See also ICM-20948 Datasheet, Register Map and Descriptions, Revision 1.3,
+// https://www.invensense.com/wp-content/uploads/2016/06/DS-000189-ICM-20948-v1.3.pdf
+// and AK09916 Datasheet and Register Map
+// https://www.akm.com/akm/en/file/datasheet/AK09916C.pdf
+
+//Magnetometer Registers
+#define AK09916_ADDRESS  0x0C 
+#define WHO_AM_I_AK09916 0x01 // (AKA WIA2) should return 0x09
+#define AK09916_ST1      0x10  // data ready status bit 0
+#define AK09916_XOUT_L   0x11  // data
+#define AK09916_XOUT_H   0x12
+#define AK09916_YOUT_L   0x13
+#define AK09916_YOUT_H   0x14
+#define AK09916_ZOUT_L   0x15
+#define AK09916_ZOUT_H   0x16
+#define AK09916_ST2      0x18  // Data overflow bit 3 and data read error status bit 2
+#define AK09916_CNTL     0x30  // Power down (0000), single-measurement (0001), self-test (1000) and Fuse ROM (1111) modes on bits 3:0
+#define AK09916_CNTL2    0x31  // Normal (0), Reset (1)
+
+// ICM-20948
+
+// USER BANK 0 REGISTER MAP
+#define WHO_AM_I_ICM20948  0x00 // Should return 0xEA
+#define USER_CTRL          0x03  // Bit 7 enable DMP, bit 3 reset DMP
+#define LP_CONFIG          0x05 // Not found in MPU-9250
+#define PWR_MGMT_1         0x06 // Device defaults to the SLEEP mode
+#define PWR_MGMT_2         0x07
+#define INT_PIN_CFG        0x0F
+#define INT_ENABLE         0x10
+#define INT_ENABLE_1       0x11 // Not found in MPU-9250
+#define INT_ENABLE_2       0x12 // Not found in MPU-9250
+#define INT_ENABLE_3       0x13 // Not found in MPU-9250
+#define I2C_MST_STATUS     0x17
+#define INT_STATUS         0x19
+#define INT_STATUS_1       0x1A // Not found in MPU-9250
+#define INT_STATUS_2       0x1B // Not found in MPU-9250
+#define INT_STATUS_3       0x1C // Not found in MPU-9250
+#define DELAY_TIMEH        0x28 // Not found in MPU-9250
+#define DELAY_TIMEL        0x29 // Not found in MPU-9250
+#define ACCEL_XOUT_H       0x2D
+#define ACCEL_XOUT_L       0x2E
+#define ACCEL_YOUT_H       0x2F
+#define ACCEL_YOUT_L       0x30
+#define ACCEL_ZOUT_H       0x31
+#define ACCEL_ZOUT_L       0x32
+#define GYRO_XOUT_H        0x33
+#define GYRO_XOUT_L        0x34
+#define GYRO_YOUT_H        0x35
+#define GYRO_YOUT_L        0x36
+#define GYRO_ZOUT_H        0x37
+#define GYRO_ZOUT_L        0x38
+#define TEMP_OUT_H         0x39
+#define TEMP_OUT_L         0x3A
+#define EXT_SENS_DATA_00   0x3B
+#define EXT_SENS_DATA_01   0x3C
+#define EXT_SENS_DATA_02   0x3D
+#define EXT_SENS_DATA_03   0x3E
+#define EXT_SENS_DATA_04   0x3F
+#define EXT_SENS_DATA_05   0x40
+#define EXT_SENS_DATA_06   0x41
+#define EXT_SENS_DATA_07   0x42
+#define EXT_SENS_DATA_08   0x43
+#define EXT_SENS_DATA_09   0x44
+#define EXT_SENS_DATA_10   0x45
+#define EXT_SENS_DATA_11   0x46
+#define EXT_SENS_DATA_12   0x47
+#define EXT_SENS_DATA_13   0x48
+#define EXT_SENS_DATA_14   0x49
+#define EXT_SENS_DATA_15   0x4A
+#define EXT_SENS_DATA_16   0x4B
+#define EXT_SENS_DATA_17   0x4C
+#define EXT_SENS_DATA_18   0x4D
+#define EXT_SENS_DATA_19   0x4E
+#define EXT_SENS_DATA_20   0x4F
+#define EXT_SENS_DATA_21   0x50
+#define EXT_SENS_DATA_22   0x51
+#define EXT_SENS_DATA_23   0x52
+#define FIFO_EN_1          0x66
+#define FIFO_EN_2          0x67 // Not found in MPU-9250
+#define FIFO_RST           0x68 // Not found in MPU-9250
+#define FIFO_MODE          0x69 // Not found in MPU-9250
+#define FIFO_COUNTH        0x70
+#define FIFO_COUNTL        0x71
+#define FIFO_R_W           0x72
+#define DATA_RDY_STATUS    0x74 // Not found in MPU-9250
+#define FIFO_CFG           0x76 // Not found in MPU-9250
+#define REG_BANK_SEL       0x7F // Not found in MPU-9250
+
+// USER BANK 1 REGISTER MAP
+#define SELF_TEST_X_GYRO            0x02
+#define SELF_TEST_Y_GYRO            0x03
+#define SELF_TEST_Z_GYRO            0x04
+#define SELF_TEST_X_ACCEL           0x0E
+#define SELF_TEST_Y_ACCEL           0x0F
+#define SELF_TEST_Z_ACCEL           0x10
+#define XA_OFFSET_H                 0x14
+#define XA_OFFSET_L                 0x15
+#define YA_OFFSET_H                 0x17
+#define YA_OFFSET_L                 0x18
+#define ZA_OFFSET_H                 0x1A
+#define ZA_OFFSET_L                 0x1B
+#define TIMEBASE_CORRECTION_PLL     0x28
+
+// USER BANK 2 REGISTER MAP
+#define GYRO_SMPLRT_DIV         0x00 // Not found in MPU-9250
+#define GYRO_CONFIG_1           0x01 // Not found in MPU-9250
+#define GYRO_CONFIG_2           0x02 // Not found in MPU-9250
+#define XG_OFFSET_H             0x03  // User-defined trim values for gyroscope
+#define XG_OFFSET_L             0x04
+#define YG_OFFSET_H             0x05
+#define YG_OFFSET_L             0x06
+#define ZG_OFFSET_H             0x07
+#define ZG_OFFSET_L             0x08
+#define ODR_ALIGN_EN            0x09 // Not found in MPU-9250
+#define ACCEL_SMPLRT_DIV_1      0x10 // Not found in MPU-9250
+#define ACCEL_SMPLRT_DIV_2      0x11 // Not found in MPU-9250
+#define ACCEL_INTEL_CTRL        0x12 // Not found in MPU-9250
+#define ACCEL_WOM_THR           0x13 // Not found in MPU-9250 (could be WOM_THR)
+#define ACCEL_CONFIG            0x14
+#define ACCEL_CONFIG_2          0x15 // Not found in MPU-9250 (could be ACCEL_CONFIG2)
+#define FSYNC_CONFIG            0x52 // Not found in MPU-9250
+#define TEMP_CONFIG             0x53 // Not found in MPU-9250
+#define MOD_CTRL_USR            0x54 // Not found in MPU-9250
+
+// USER BANK 3 REGISTER MAP
+#define I2C_MST_ODR_CONFIG      0x00 // Not found in MPU-9250
+#define I2C_MST_CTRL            0x01
+#define I2C_MST_DELAY_CTRL      0x02
+#define I2C_SLV0_ADDR           0x03
+#define I2C_SLV0_REG            0x04
+#define I2C_SLV0_CTRL           0x05
+#define I2C_SLV0_DO             0x06
+#define I2C_SLV1_ADDR           0x07
+#define I2C_SLV1_REG            0x08
+#define I2C_SLV1_CTRL           0x09
+#define I2C_SLV1_DO             0x0A
+#define I2C_SLV2_ADDR           0x0B
+#define I2C_SLV2_REG            0x0C
+#define I2C_SLV2_CTRL           0x0D
+#define I2C_SLV2_DO             0x0E
+#define I2C_SLV3_ADDR           0x0F
+#define I2C_SLV3_REG            0x10
+#define I2C_SLV3_CTRL           0x11
+#define I2C_SLV3_DO             0x12
+#define I2C_SLV4_ADDR           0x13
+#define I2C_SLV4_REG            0x14
+#define I2C_SLV4_CTRL           0x15
+#define I2C_SLV4_DO             0x16
+#define I2C_SLV4_DI             0x17
+
+
+// Using the ICM-20948 breakout board, ADO is set to 1
+// Seven-bit device address is 1000100 for ADO = 0 and 1000101 for ADO = 1
+#define ADO 1
+#if ADO
+#define ICM20948_ADDRESS 0x69  // Device address when ADO = 1
+#else
+#define ICM20948_ADDRESS 0x68  // Device address when ADO = 0
+#define AK09916_ADDRESS  0x0C   // Address of magnetometer
+#endif // AD0
+
+#define READ_FLAG 0x80
+#define NOT_SPI -1
+#define SPI_DATA_RATE 1000000 // 1MHz is the max speed of the ICM-20948
+//#define SPI_DATA_RATE 1000000 // 1MHz is the max speed of the ICM-20948
+#define SPI_MODE SPI_MODE3
+
+class ICM20948
+{
+  protected:
+    // Set initial input parameters
+    enum Ascale
+    {
+      AFS_2G = 0,
+      AFS_4G,
+      AFS_8G,
+      AFS_16G
+    };
+
+    enum Gscale {
+      GFS_250DPS = 0,
+      GFS_500DPS,
+      GFS_1000DPS,
+      GFS_2000DPS
+    };
+
+    enum Mscale {
+      MFS_14BITS = 0, // 0.6 mG per LSB
+      MFS_16BITS      // 0.15 mG per LSB
+    };
+
+    enum M_MODE {
+      M_8HZ = 0x02,  // 8 Hz update
+      M_100HZ = 0x06 // 100 Hz continuous magnetometer
+    };
+
+    // TODO: Add setter methods for this hard coded stuff
+    // Specify sensor full scale
+    uint8_t Gscale = GFS_250DPS;
+    uint8_t Ascale = AFS_2G;
+
+    // 2 for 8 Hz, 6 for 100 Hz continuous magnetometer data read
+    uint8_t Mmode = M_100HZ;
+
+    // SPI chip select pin
+    int8_t _csPin;
+
+    uint8_t writeByteWire(uint8_t, uint8_t, uint8_t);
+    uint8_t writeByteSPI(uint8_t, uint8_t);
+    uint8_t readByteSPI(uint8_t subAddress);
+    uint8_t readByteWire(uint8_t address, uint8_t subAddress);
+    bool magInit();
+    void kickHardware();
+    void select();
+    void deselect();
+// TODO: Remove this next line
+public:
+    uint8_t ak09916WhoAmI_SPI();
+
+  public:
+    float pitch, yaw, roll;
+    float temperature;   // Stores the real internal chip temperature in Celsius
+    int16_t tempCount;   // Temperature raw count output
+    uint32_t delt_t = 0; // Used to control display output rate
+
+    uint32_t count = 0, sumCount = 0; // used to control display output rate
+    float deltat = 0.0f, sum = 0.0f;  // integration interval for both filter schemes
+    uint32_t lastUpdate = 0, firstUpdate = 0; // used to calculate integration interval
+    uint32_t Now = 0;        // used to calculate integration interval
+
+    int16_t gyroCount[3];   // Stores the 16-bit signed gyro sensor output
+    int16_t magCount[3];    // Stores the 16-bit signed magnetometer sensor output
+    // Scale resolutions per LSB for the sensors
+    float aRes, gRes, mRes;
+    // Variables to hold latest sensor data values
+    float ax, ay, az, gx, gy, gz, mx, my, mz;
+    // Factory mag calibration and mag bias
+    float factoryMagCalibration[3] = {0, 0, 0}, factoryMagBias[3] = {0, 0, 0};
+    // Bias corrections for gyro, accelerometer, and magnetometer
+    float gyroBias[3]  = {0, 0, 0},
+          accelBias[3] = {0, 0, 0},
+          magBias[3]   = {0, 0, 0},
+          magScale[3]  = {0, 0, 0};
+    float selfTest[6];
+    // Stores the 16-bit signed accelerometer sensor output
+    int16_t accelCount[3];
+
+    // Public method declarations
+    ICM20948(int8_t csPin=NOT_SPI);
+    void getMres();
+    void getGres();
+    void getAres();
+    void readAccelData(int16_t *);
+    void readGyroData(int16_t *);
+    void readMagData(int16_t *);
+    int16_t readTempData();
+    void updateTime();
+    void initAK09916();
+    void initICM20948();
+    void calibrateICM20948(float * gyroBias, float * accelBias);
+    void ICM20948SelfTest(float * destination);
+    void magCalICM20948(float * dest1, float * dest2);
+    uint8_t writeByte(uint8_t, uint8_t, uint8_t);
+    uint8_t readByte(uint8_t, uint8_t);
+    uint8_t readBytes(uint8_t, uint8_t, uint8_t, uint8_t *);
+    // TODO: make SPI/Wire private
+    uint8_t readBytesSPI(uint8_t, uint8_t, uint8_t *);
+    uint8_t readBytesWire(uint8_t, uint8_t, uint8_t, uint8_t *);
+    bool isInI2cMode() { return _csPin == -1; }
+    bool begin();
+};  // class ICM20948
+
+#endif // _ICM20948_H_
\ No newline at end of file