

# ICM 20948 driver for STM32

Basic driver for TDK InvenSense ICM-20948. It support 2 modes:

- pooling
- interrupt

## Public API

Class `Icm20948`
- `void Stop(void)` - stop the continuous measuring
- `void Start(void)` - start the automatic/continuous measure
- `void Sleep() / void Wakeup()`  put to sleep/wakeup sensor
- `void Reset()` reinitialise sensor
- `uint8_t GetDataStatus(void)` return 1, when data is ready to read
- `bool IsReady()` get status information. The state can be changed by Start/Stop methods
- `uint8_t IsSleep()` return 1, is device is in sleep mode
- `void Read()` perform data read from device; from all sensors: accelerometer, gyroscope and Magnetometer (if is enabled)
- `void Calibrate(*config)`  - perform calibration and put configuration (Low pass filter, sample rate, scale) fo sensors, if `config` is not NULL
- `void SetInterruptSource(source)` Source can be: interrupt_disable, interrupt_DMP_INT1_EN, interrupt_PLL_RDY_EN, interrupt_WOM_INT_EN, interrupt_REG_WOF_EN, interrupt_RAW_DATA_0_RDY_EN
- public members:
-- `SensorAccel` - accelerometer
-- `SensorGyro` - gyroscope
-- `SensorMag` - magneometer

Public methods in class for sensor representation `Sensor`:
- `void SetScaleFactor(float sf)`
- `void SetRange(range) / uint8_t GetRange()`
- `void SetLowPassFilter(filter) / uint8_t GetLowPassFilter()`
- `uint8_t SetSampleRate(value) / uint8_t GetSampleRate()`
- `void Calibrate(void)`
- `uint8_t GetDataStatus(void)`  return 1 whed data are ready to read
- `axisesI *GetData(void)` - return pointer to measured data. Data have to be previously read by ICM20948::Read method
- `bool Read(axisesI *)` peform local read from single sensor
- `bool ReadUnit(axisesF*)`peform local read from single sensor, make recalculation to real values (acceleration, angular speed) as floats

# Working modes

## Pooling
```c
#include <stdlib.h>
#include "icm20948.h"

int main(void)
{
  // HAL_Init, etc...

  SpiManager manager(&hspi2);

  icm20948_Config config;
  config.pinCS = &pinCS;
  config.gyro.low_pass_filter = GYRO_lpf_196_6Hz;
  config.gyro.sample_rate = GYRO_samplerate_281_3Hz;
  config.accel.low_pass_filter = ACCEL_lpf_246Hz;
  config.accel.sample_rate = ACCEL_samplerate_281_3Hz;

  Icm20948 sensor(&manager, &config2);

 axisesF sensor_dataF;  // float values
 axisesI sensor_dataI;  // int16 values

  while (1)
  {
    // read raw values
    if(sensor.GetDataStatus() == 1 ){
      //read raw data
      sensor.accSensor->Read(&sensor_dataI);
      sensor.gyroSensor->Read(&sensor_dataI);
      sensor.magSensor->Read(&sensor_dataI);

      // or unit conversion
      sensor.accSensor->ReadUnit(&sensor_dataF);
      sensor.gyroSensor->ReadUnit(&sensor_dataF);
      sensor.magSensor->ReadUnit(&sensor_dataF);
    }

  }
}

```

## Interrupt

```c

#include "icm20948.h"


Device_TypeDef *module;
volatile uint8_t icm_ready;


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == ICM_INT_Pin){
    icm_ready = 1;
  }
}


int main(void)
{

  // HAL_Init, etc...

  axises *my_gyro1 = NULL;
  axises *my_accel1 = NULL;

  SpiManager manager(&hspi2);
  
  icm20948_Config config1;
  config1.pinCS = &pinCS;
  config1.pinINT = &pinINT;
  config1.gyro.low_pass_filter = GYRO_lpf_196_6Hz;
  config1.gyro.sample_rate = GYRO_samplerate_281_3Hz;
  config1.accel.low_pass_filter = ACCEL_lpf_246Hz;
  config1.accel.sample_rate = ACCEL_samplerate_281_3Hz;
  config1.mag.mode = mag_mode_cont_measurement_100hz;
  config1.int_source = interrupt_RAW_DATA_0_RDY_EN;

  while (1)
  {
    if(icm_ready1 == 1){
      icm_ready1 = 0;

      sensor1.Read();   // read data from sensors

      my_accel1 = sensor1.accSensor->GetData(); // only return prepared data
      my_gyro1 = sensor1.gyroSensor->GetData();
      my_mag1 = sensor1.magSensor->GetData();
    }
  }
}

```
