3-axis MEMS ultra low power magnetometer

Dependencies:   X_NUCLEO_COMMON ST_INTERFACES

Dependents:   X_NUCLEO_IKS01A3 X_NUCLEO_IKS01A3

Files at this revision

API Documentation at this revision

Comitter:
cparata
Date:
Tue Mar 05 18:06:37 2019 +0000
Child:
1:8562ae1a0534
Commit message:
First version of LIS2MDL library

Changed in this revision

LIS2MDLSensor.cpp Show annotated file Show diff for this revision Revisions of this file
LIS2MDLSensor.h Show annotated file Show diff for this revision Revisions of this file
ST_INTERFACES.lib Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_COMMON.lib Show annotated file Show diff for this revision Revisions of this file
lis2mdl_reg.c Show annotated file Show diff for this revision Revisions of this file
lis2mdl_reg.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LIS2MDLSensor.cpp	Tue Mar 05 18:06:37 2019 +0000
@@ -0,0 +1,415 @@
+/**
+ ******************************************************************************
+ * @file    LIS2MDLSensor.cpp
+ * @author  SRA
+ * @version V1.0.0
+ * @date    February 2019
+ * @brief   Implementation of an LIS2MDL 3 axes magnetometer sensor.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2019 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of STMicroelectronics nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "LIS2MDLSensor.h"
+
+
+/* Class Implementation ------------------------------------------------------*/
+
+/** Constructor
+ * @param spi object of an helper class which handles the SPI peripheral
+ * @param cs_pin the chip select pin
+ * @param int_pin the interrupt pin
+ * @param spi_type the SPI type
+ */
+LIS2MDLSensor::LIS2MDLSensor(SPI *spi, PinName cs_pin, PinName int_pin, SPI_type_t spi_type) : _dev_spi(spi), _cs_pin(cs_pin), _int_irq(int_pin), _spi_type(spi_type)
+{
+  assert (spi);
+  if (cs_pin == NC) 
+  {
+    printf ("ERROR LIS2MDL CS MUST NOT BE NC\n\r");       
+    _dev_spi = NULL;
+    _dev_i2c = NULL;
+    return;
+  }
+
+  _reg_ctx.write_reg = LIS2MDL_io_write;
+  _reg_ctx.read_reg = LIS2MDL_io_read;
+  _reg_ctx.handle = (void *)this;
+  _cs_pin = 1;    
+  _dev_i2c = NULL;
+  _address = 0;
+    
+  if (_spi_type == SPI4W)
+  {
+    /* Enable SPI 4-Wires on the component (in this way we lose the usage of INT pin) */
+    uint8_t data = 0x34;
+    lis2mdl_write_reg(&_reg_ctx, LIS2MDL_CFG_REG_C, &data, 1);
+  }
+}
+
+/** Constructor
+ * @param i2c object of an helper class which handles the I2C peripheral
+ * @param address the address of the component's instance
+ * @param int_pin the interrupt pin
+ */
+LIS2MDLSensor::LIS2MDLSensor(DevI2C *i2c, uint8_t address, PinName int_pin) : _dev_i2c(i2c), _address(address), _cs_pin(NC), _int_irq(int_pin)
+{
+  assert (i2c);
+  _dev_spi = NULL;
+  _reg_ctx.write_reg = LIS2MDL_io_write;
+  _reg_ctx.read_reg = LIS2MDL_io_read;
+  _reg_ctx.handle = (void *)this;
+}
+
+/**
+ * @brief  Initializing the component
+ * @param  init pointer to device specific initalization structure
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::init(void *init)
+{
+  /* Enable BDU */
+  if (lis2mdl_block_data_update_set(&(_reg_ctx), PROPERTY_ENABLE) != 0)
+  {
+    return 1;
+  }
+
+  /* Operating mode selection - power down */
+  if (lis2mdl_operating_mode_set(&(_reg_ctx), LIS2MDL_POWER_DOWN) != 0)
+  {
+    return 1;
+  }
+
+  /* Output data rate selection */
+  if (lis2mdl_data_rate_set(&(_reg_ctx), LIS2MDL_ODR_100Hz) != 0)
+  {
+    return 1;
+  }
+
+  /* Self Test disabled. */
+  if (lis2mdl_self_test_set(&(_reg_ctx), PROPERTY_DISABLE) != 0)
+  {
+    return 1;
+  }
+
+  _mag_is_enabled = 0;
+
+  return 0;
+}
+
+/**
+ * @brief  Read component ID
+ * @param  id the WHO_AM_I value
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::read_id(uint8_t *id)
+{
+  if (lis2mdl_device_id_get(&_reg_ctx, id) != 0)
+  {
+    return 1;
+  }
+
+  return 0;
+}
+
+
+/**
+ * @brief Enable the LIS2MDL magnetometer sensor
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::enable()
+{
+  /* Check if the component is already enabled */
+  if (_mag_is_enabled == 1U)
+  {
+    return 0;
+  }
+
+  /* Output data rate selection. */
+  if (lis2mdl_operating_mode_set(&_reg_ctx, LIS2MDL_CONTINUOUS_MODE) != 0)
+  {
+    return 1;
+  }
+
+  _mag_is_enabled = 1;
+
+  return 0;
+}
+
+/**
+ * @brief Disable the LIS2MDL magnetometer sensor
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::disable()
+{
+  /* Check if the component is already disabled */
+  if (_mag_is_enabled == 0U)
+  {
+    return 0;
+  }
+
+  /* Output data rate selection - power down. */
+  if (lis2mdl_operating_mode_set(&_reg_ctx, LIS2MDL_POWER_DOWN) != 0)
+  {
+    return 1;
+  }
+
+  _mag_is_enabled = 0;
+
+  return 0;
+}
+
+/**
+ * @brief  Get the LIS2MDL magnetometer sensor sensitivity
+ * @param  sensitivity pointer where the sensitivity is written
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::get_m_sensitivity(float *sensitivity)
+{
+  *sensitivity = LIS2MDL_MAG_SENSITIVITY_FS_50GAUSS;
+
+  return 0;
+}
+
+/**
+ * @brief  Get the LIS2MDL magnetometer sensor output data rate
+ * @param  odr pointer where the output data rate is written
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::get_m_odr(float *odr)
+{
+  int ret = 0;
+  lis2mdl_odr_t odr_low_level;
+
+  /* Get current output data rate. */
+  if (lis2mdl_data_rate_get(&_reg_ctx, &odr_low_level) != 0)
+  {
+    return 1;
+  }
+
+  switch (odr_low_level)
+  {
+    case LIS2MDL_ODR_10Hz:
+      *odr = 10.0f;
+      break;
+
+    case LIS2MDL_ODR_20Hz:
+      *odr = 20.0f;
+      break;
+
+    case LIS2MDL_ODR_50Hz:
+      *odr = 50.0f;
+      break;
+
+    case LIS2MDL_ODR_100Hz:
+      *odr = 100.0f;
+      break;
+
+    default:
+      ret = 1;
+      break;
+  }
+
+  return ret;
+}
+
+/**
+ * @brief  Set the LIS2MDL magnetometer sensor output data rate
+ * @param  odr the output data rate value to be set
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::set_m_odr(float odr)
+{
+  lis2mdl_odr_t new_odr;
+
+  new_odr = (odr <= 10.000f) ? LIS2MDL_ODR_10Hz
+          : (odr <= 20.000f) ? LIS2MDL_ODR_20Hz
+          : (odr <= 50.000f) ? LIS2MDL_ODR_50Hz
+          :                    LIS2MDL_ODR_100Hz;
+
+  if (lis2mdl_data_rate_set(&_reg_ctx, new_odr) != 0)
+  {
+    return 1;
+  }
+
+  return 0;
+}
+
+/**
+ * @brief  Get the LIS2MDL magnetometer sensor full scale
+ * @param  full_scale pointer where the full scale is written
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::get_m_fs(float *full_scale)
+{
+  *full_scale = 50.0f;
+
+  return 0;
+}
+
+/**
+ * @brief  Set the LIS2MDL magnetometer sensor full scale
+ * @param  full_scale the functional full scale to be set
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::set_m_fs(float full_scale)
+{
+  (void)full_scale;
+  return 0;
+}
+
+/**
+ * @brief  Get the LIS2MDL magnetometer sensor axes
+ * @param  magnetic_field pointer where the values of the axes are written
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::get_m_axes(int32_t *magnetic_field)
+{
+  axis3bit16_t data_raw;
+  float sensitivity;
+
+  /* Read raw data values. */
+  if (lis2mdl_magnetic_raw_get(&_reg_ctx, data_raw.u8bit) != 0)
+  {
+    return 1;
+  }
+
+  /* Get LIS2MDL actual sensitivity. */
+  if (get_m_sensitivity(&sensitivity) != 0)
+  {
+    return 1;
+  }
+
+  /* Calculate the data. */
+  magnetic_field[0] = (int32_t)((float)((float)data_raw.i16bit[0] * sensitivity));
+  magnetic_field[1] = (int32_t)((float)((float)data_raw.i16bit[1] * sensitivity));
+  magnetic_field[2] = (int32_t)((float)((float)data_raw.i16bit[2] * sensitivity));
+
+  return 0;
+}
+
+/**
+ * @brief  Get the LIS2MDL magnetometer sensor raw axes
+ * @param  value pointer where the raw values of the axes are written
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::get_m_axes_raw(int16_t *value)
+{
+  axis3bit16_t data_raw;
+
+  /* Read raw data values. */
+  if (lis2mdl_magnetic_raw_get(&_reg_ctx, data_raw.u8bit) != 0)
+  {
+    return 1;
+  }
+
+  /* Format the data. */
+  value[0] = data_raw.i16bit[0];
+  value[1] = data_raw.i16bit[1];
+  value[2] = data_raw.i16bit[2];
+
+  return 0;
+}
+
+/**
+ * @brief  Get the LIS2MDL register value for magnetic sensor
+ * @param  reg address to be read
+ * @param  data pointer where the value is written
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::read_reg(uint8_t reg, uint8_t *data)
+{
+  if (lis2mdl_read_reg(&_reg_ctx, reg, data, 1) != 0)
+  {
+    return 1;
+  }
+
+  return 0;
+}
+
+/**
+ * @brief  Set the LIS2MDL register value for magnetic sensor
+ * @param  pObj the device pObj
+ * @param  reg address to be written
+ * @param  data value to be written
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::write_reg(uint8_t reg, uint8_t data)
+{
+  if (lis2mdl_write_reg(&_reg_ctx, reg, &data, 1) != 0)
+  {
+    return 1;
+  }
+
+  return 0;
+}
+
+/**
+ * @brief  Set self test
+ * @param  status the value of self_test in reg CFG_REG_C
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::set_m_self_test(uint8_t status)
+{
+  if (lis2mdl_self_test_set(&_reg_ctx, status) != 0)
+  {
+    return 1;
+  }
+
+  return 0;
+}
+
+/**
+ * @brief  Get the LIS2MDL MAG data ready bit value
+ * @param  status the status of data ready bit
+ * @retval 0 in case of success, an error code otherwise
+ */
+int LIS2MDLSensor::get_m_drdy_status(uint8_t *status)
+{
+  if (lis2mdl_mag_data_ready_get(&_reg_ctx, status) != 0)
+  {
+    return 1;
+  }
+
+  return 0;
+}
+
+
+
+int32_t LIS2MDL_io_write(void *handle, uint8_t WriteAddr, uint8_t *pBuffer, uint16_t nBytesToWrite)
+{
+  return ((LIS2MDLSensor *)handle)->io_write(pBuffer, WriteAddr, nBytesToWrite);
+}
+
+int32_t LIS2MDL_io_read(void *handle, uint8_t ReadAddr, uint8_t *pBuffer, uint16_t nBytesToRead)
+{
+  return ((LIS2MDLSensor *)handle)->io_read(pBuffer, ReadAddr, nBytesToRead);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LIS2MDLSensor.h	Tue Mar 05 18:06:37 2019 +0000
@@ -0,0 +1,212 @@
+/**
+ ******************************************************************************
+ * @file    LIS2MDLSensor.h
+ * @author  SRA
+ * @version V1.0.0
+ * @date    February 2019
+ * @brief   Abstract Class of an LIS2MDL 3 axes magnetometer sensor.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2019 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright notice,
+ *      this list of conditions and the following disclaimer in the documentation
+ *      and/or other materials provided with the distribution.
+ *   3. Neither the name of STMicroelectronics nor the names of its contributors
+ *      may be used to endorse or promote products derived from this software
+ *      without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ******************************************************************************
+ */
+
+
+/* Prevent recursive inclusion -----------------------------------------------*/
+
+#ifndef __LIS2MDLSensor_H__
+#define __LIS2MDLSensor_H__
+
+
+/* Includes ------------------------------------------------------------------*/
+
+#include "DevI2C.h"
+#include "lis2mdl_reg.h"
+#include "MagneticSensor.h"
+#include <assert.h>
+
+/* Defines -------------------------------------------------------------------*/
+
+
+#define LIS2MDL_MAG_SENSITIVITY_FS_50GAUSS  1.500f  /**< Sensitivity value for 50 gauss full scale [mgauss/LSB] */
+
+/* Typedefs ------------------------------------------------------------------*/
+
+typedef struct
+{
+  int16_t x;
+  int16_t y;
+  int16_t z;
+} LIS2MDL_AxesRaw_t;
+
+typedef struct
+{
+  int32_t x;
+  int32_t y;
+  int32_t z;
+} LIS2MDL_Axes_t;
+
+
+/* Class Declaration ---------------------------------------------------------*/
+   
+/**
+ * Abstract class of an LIS2MDL Inertial Measurement Unit (IMU) 3 axes
+ * sensor.
+ */
+class LIS2MDLSensor : public MagneticSensor
+{
+  public:
+    enum SPI_type_t {SPI3W, SPI4W};
+    LIS2MDLSensor(SPI *spi, PinName cs_pin, PinName int_pin=NC, SPI_type_t spi_type=SPI4W);
+    LIS2MDLSensor(DevI2C *i2c, uint8_t address=LIS2MDL_I2C_ADD, PinName int_pin=NC);
+    virtual int init(void *init);
+    virtual int read_id(uint8_t *id);
+    virtual int get_m_axes(int32_t *magnetic_field);
+    virtual int get_m_axes_raw(int16_t *value);
+    int enable(void);
+    int disable(void);
+    int get_m_sensitivity(float *sensitivity);
+    int get_m_odr(float *odr);
+    int set_m_odr(float odr);
+    int get_m_fs(float *full_scale);
+    int set_m_fs(float full_scale);
+    int read_reg(uint8_t reg, uint8_t *data);
+    int write_reg(uint8_t reg, uint8_t data);
+    int set_m_self_test(uint8_t status);
+    int get_m_drdy_status(uint8_t *status);
+
+    /**
+     * @brief  Attaching an interrupt handler to the INT interrupt.
+     * @param  fptr An interrupt handler.
+     * @retval None.
+     */
+    void attach_int_irq(void (*fptr)(void))
+    {
+        _int_irq.rise(fptr);
+    }
+
+    /**
+     * @brief  Enabling the INT interrupt handling.
+     * @param  None.
+     * @retval None.
+     */
+    void enable_int_irq(void)
+    {
+        _int_irq.enable_irq();
+    }
+    
+    /**
+     * @brief  Disabling the INT interrupt handling.
+     * @param  None.
+     * @retval None.
+     */
+    void disable_int_irq(void)
+    {
+        _int_irq.disable_irq();
+    }
+
+    /**
+     * @brief Utility function to read data.
+     * @param  pBuffer: pointer to data to be read.
+     * @param  RegisterAddr: specifies internal address register to be read.
+     * @param  NumByteToRead: number of bytes to be read.
+     * @retval 0 if ok, an error code otherwise.
+     */
+    uint8_t io_read(uint8_t* pBuffer, uint8_t RegisterAddr, uint16_t NumByteToRead)
+    {
+        if (_dev_spi) {
+            /* Write Reg Address */
+            _dev_spi->lock();
+            _cs_pin = 0;           
+            if (_spi_type == SPI4W) {            
+                _dev_spi->write(RegisterAddr | 0x80);
+                for (int i=0; i<NumByteToRead; i++) {
+                    *(pBuffer+i) = _dev_spi->write(0x00);
+                }
+            } else if (_spi_type == SPI3W){
+                /* Write RD Reg Address with RD bit*/
+                uint8_t TxByte = RegisterAddr | 0x80;    
+                _dev_spi->write((char *)&TxByte, 1, (char *)pBuffer, (int) NumByteToRead);
+            }            
+            _cs_pin = 1;
+            _dev_spi->unlock(); 
+            return 0;
+        }                       
+        if (_dev_i2c) return (uint8_t) _dev_i2c->i2c_read(pBuffer, _address, RegisterAddr, NumByteToRead);
+        return 1;
+    }
+    
+    /**
+     * @brief Utility function to write data.
+     * @param  pBuffer: pointer to data to be written.
+     * @param  RegisterAddr: specifies internal address register to be written.
+     * @param  NumByteToWrite: number of bytes to write.
+     * @retval 0 if ok, an error code otherwise.
+     */
+    uint8_t io_write(uint8_t* pBuffer, uint8_t RegisterAddr, uint16_t NumByteToWrite)
+    {
+        if (_dev_spi) { 
+            _dev_spi->lock();
+            _cs_pin = 0;
+            _dev_spi->write(RegisterAddr);                    
+            _dev_spi->write((char *)pBuffer, (int) NumByteToWrite, NULL, 0);                     
+            _cs_pin = 1;                    
+            _dev_spi->unlock();
+            return 0;                    
+        }        
+        if (_dev_i2c) return (uint8_t) _dev_i2c->i2c_write(pBuffer, _address, RegisterAddr, NumByteToWrite);    
+        return 1;
+    }
+
+  private:
+
+    /* Helper classes. */
+    DevI2C *_dev_i2c;
+    SPI    *_dev_spi;
+
+    /* Configuration */
+    uint8_t _address;
+    DigitalOut  _cs_pin;        
+    InterruptIn _int_irq;
+    SPI_type_t _spi_type;
+    
+    uint8_t _mag_is_enabled;
+    
+    lis2mdl_ctx_t _reg_ctx;
+    
+};
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+int32_t LIS2MDL_io_write( void *handle, uint8_t WriteAddr, uint8_t *pBuffer, uint16_t nBytesToWrite );
+int32_t LIS2MDL_io_read( void *handle, uint8_t ReadAddr, uint8_t *pBuffer, uint16_t nBytesToRead );
+#ifdef __cplusplus
+  }
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ST_INTERFACES.lib	Tue Mar 05 18:06:37 2019 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/ST/code/ST_INTERFACES/#d3c9b33b992c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_COMMON.lib	Tue Mar 05 18:06:37 2019 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/teams/ST/code/X_NUCLEO_COMMON/#21096473f63e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lis2mdl_reg.c	Tue Mar 05 18:06:37 2019 +0000
@@ -0,0 +1,1156 @@
+/*
+ ******************************************************************************
+ * @file    lis2mdl_reg.c
+ * @author  Sensors Software Solution Team
+ * @brief   LIS2MDL driver file
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2018 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *   3. Neither the name of STMicroelectronics nor the names of its
+ *      contributors may be used to endorse or promote products derived from
+ *      this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+*/
+#include "lis2mdl_reg.h"
+
+/**
+  * @defgroup    LIS2MDL
+  * @brief       This file provides a set of functions needed to drive the
+  *              lis2mdl enhanced inertial module.
+  * @{
+  *
+  */
+
+/**
+  * @defgroup    LIS2MDL_Interfaces_Functions
+  * @brief       This section provide a set of functions used to read and
+  *              write a generic register of the device.
+  *              MANDATORY: return 0 -> no Error.
+  * @{
+  *
+  */
+
+/**
+  * @brief  Read generic device register
+  *
+  * @param  ctx   read / write interface definitions(ptr)
+  * @param  reg   register to read
+  * @param  data  pointer to buffer that store the data read(ptr)
+  * @param  len   number of consecutive register to read
+  * @retval       interface status (MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_read_reg(lis2mdl_ctx_t* ctx, uint8_t reg, uint8_t* data,
+                         uint16_t len)
+{
+  int32_t ret;
+  ret = ctx->read_reg(ctx->handle, reg, data, len);
+  return ret;
+}
+
+/**
+  * @brief  Write generic device register
+  *
+  * @param  ctx   read / write interface definitions(ptr)
+  * @param  reg   register to write
+  * @param  data  pointer to data to write in register reg(ptr)
+  * @param  len   number of consecutive register to write
+  * @retval       interface status (MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_write_reg(lis2mdl_ctx_t* ctx, uint8_t reg, uint8_t* data,
+                          uint16_t len)
+{
+  int32_t ret;
+  ret = ctx->write_reg(ctx->handle, reg, data, len);
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+  /**
+  * @defgroup    LIS2MDL_Sensitivity
+  * @brief       These functions convert raw-data into engineering units.
+  * @{
+  *
+  */
+float_t lis2mdl_from_lsb_to_mgauss(int16_t lsb)
+{
+  return ((float_t)lsb * 1.5f);
+}
+
+float_t lis2mdl_from_lsb_to_celsius(int16_t lsb)
+{
+  return (((float_t)lsb / 8.0f) + 25.0f);
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LIS2MDL_data_generation
+  * @brief       This section group all the functions concerning
+  *              data generation
+  * @{
+  *
+  */
+
+/**
+  * @brief  These registers comprise a 3 group of 16-bit number and represent
+  *         hard-iron offset in order to compensate environmental effects.
+  *         Data format is the same of output data raw: two’s complement
+  *         with 1LSb = 1.5mG. These values act on the magnetic output data
+  *         value in order to delete the environmental offset.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  buff  buffer that contains data to write
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_mag_user_offset_set(lis2mdl_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+  ret = lis2mdl_write_reg(ctx, LIS2MDL_OFFSET_X_REG_L, buff, 6);
+  return ret;
+}
+
+/**
+  * @brief  These registers comprise a 3 group of 16-bit number and represent
+  *         hard-iron offset in order to compensate environmental effects.
+  *         Data format is the same of output data raw: two’s complement
+  *         with 1LSb = 1.5mG. These values act on the magnetic output data
+  *         value in order to delete the environmental offset.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  buff  that stores data read
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_mag_user_offset_get(lis2mdl_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_OFFSET_X_REG_L, buff, 6);
+  return ret;
+}
+
+/**
+  * @brief  Operating mode selection.[set]
+  *
+  * @param  ctx    read / write interface definitions.(ptr)
+  * @param  val    change the values of md in reg CFG_REG_A
+  * @retval        interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_operating_mode_set(lis2mdl_ctx_t *ctx, lis2mdl_md_t val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.md = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Operating mode selection.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of md in reg CFG_REG_A.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_operating_mode_get(lis2mdl_ctx_t *ctx, lis2mdl_md_t *val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  switch (reg.md){
+    case LIS2MDL_POWER_DOWN:
+      *val = LIS2MDL_POWER_DOWN;
+      break;
+    case LIS2MDL_CONTINUOUS_MODE:
+      *val = LIS2MDL_CONTINUOUS_MODE;
+      break;
+    case LIS2MDL_SINGLE_TRIGGER:
+      *val = LIS2MDL_SINGLE_TRIGGER;
+      break;
+    default:
+      *val = LIS2MDL_POWER_DOWN;
+      break;
+  }  
+
+  return ret;
+}
+
+/**
+  * @brief  Output data rate selection.[set] 
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of odr in reg CFG_REG_A
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_data_rate_set(lis2mdl_ctx_t *ctx, lis2mdl_odr_t val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.odr = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Output data rate selection.[get] 
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of odr in reg CFG_REG_A.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_data_rate_get(lis2mdl_ctx_t *ctx, lis2mdl_odr_t *val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  switch (reg.odr){
+    case LIS2MDL_ODR_10Hz:
+      *val = LIS2MDL_ODR_10Hz;
+      break;
+    case LIS2MDL_ODR_20Hz:
+      *val = LIS2MDL_ODR_20Hz;
+      break;
+    case LIS2MDL_ODR_50Hz:
+      *val = LIS2MDL_ODR_50Hz;
+      break;
+    case LIS2MDL_ODR_100Hz:
+      *val = LIS2MDL_ODR_100Hz;
+      break;
+    default:
+      *val = LIS2MDL_ODR_10Hz;
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  Enables high-resolution/low-power mode.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of lp in reg CFG_REG_A
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_power_mode_set(lis2mdl_ctx_t *ctx, lis2mdl_lp_t val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.lp = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Enables high-resolution/low-power mode.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of lp in reg CFG_REG_A.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_power_mode_get(lis2mdl_ctx_t *ctx, lis2mdl_lp_t *val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  switch (reg.lp){
+    case LIS2MDL_HIGH_RESOLUTION:
+      *val = LIS2MDL_HIGH_RESOLUTION;
+      break;
+    case LIS2MDL_LOW_POWER:
+      *val = LIS2MDL_LOW_POWER;
+      break;
+    default:
+      *val = LIS2MDL_HIGH_RESOLUTION;
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  Enables the magnetometer temperature compensation.[set] 
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of comp_temp_en in reg CFG_REG_A
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_offset_temp_comp_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.comp_temp_en = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Enables the magnetometer temperature compensation.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of comp_temp_en in reg CFG_REG_A.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_offset_temp_comp_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  *val = reg.comp_temp_en;
+
+  return ret;
+}
+
+/**
+  * @brief  Low-pass bandwidth selection.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of lpf in reg CFG_REG_B
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_low_pass_bandwidth_set(lis2mdl_ctx_t *ctx,
+                                       lis2mdl_lpf_t val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.lpf = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Low-pass bandwidth selection.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of lpf in reg CFG_REG_B.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_low_pass_bandwidth_get(lis2mdl_ctx_t *ctx,
+                                       lis2mdl_lpf_t *val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  switch (reg.lpf){
+    case LIS2MDL_ODR_DIV_2:
+      *val = LIS2MDL_ODR_DIV_2;
+      break;
+    case LIS2MDL_ODR_DIV_4:
+      *val = LIS2MDL_ODR_DIV_4;
+      break;
+    default:
+      *val = LIS2MDL_ODR_DIV_2;
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  Reset mode.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of set_rst in reg CFG_REG_B
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_set_rst_mode_set(lis2mdl_ctx_t *ctx, lis2mdl_set_rst_t val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.set_rst = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Reset mode.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of set_rst in reg CFG_REG_B.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_set_rst_mode_get(lis2mdl_ctx_t *ctx, lis2mdl_set_rst_t *val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  switch (reg.set_rst){
+    case LIS2MDL_SET_SENS_ODR_DIV_63:
+      *val = LIS2MDL_SET_SENS_ODR_DIV_63;
+      break;
+    case LIS2MDL_SENS_OFF_CANC_EVERY_ODR:
+      *val = LIS2MDL_SENS_OFF_CANC_EVERY_ODR;
+      break;
+    case LIS2MDL_SET_SENS_ONLY_AT_POWER_ON:
+      *val = LIS2MDL_SET_SENS_ONLY_AT_POWER_ON;
+      break;
+    default:
+      *val = LIS2MDL_SET_SENS_ODR_DIV_63;
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  Enables offset cancellation in single measurement mode. 
+  *         The OFF_CANC bit must be set to 1 when enabling offset
+  *         cancellation in single measurement mode this means a
+  *         call function: set_rst_mode(SENS_OFF_CANC_EVERY_ODR)
+  *         is need.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of off_canc_one_shot in reg CFG_REG_B
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_set_rst_sensor_single_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.off_canc_one_shot = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Enables offset cancellation in single measurement mode. 
+  *         The OFF_CANC bit must be set to 1 when enabling offset
+  *         cancellation in single measurement mode this means a
+  *         call function: set_rst_mode(SENS_OFF_CANC_EVERY_ODR)
+  *         is need.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of off_canc_one_shot in reg CFG_REG_B.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_set_rst_sensor_single_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  *val = reg.off_canc_one_shot;
+
+  return ret;
+}
+
+/**
+  * @brief  Blockdataupdate.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of bdu in reg CFG_REG_C
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_block_data_update_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.bdu = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Blockdataupdate.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of bdu in reg CFG_REG_C.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_block_data_update_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  *val = reg.bdu;
+
+  return ret;
+}
+
+/**
+  * @brief  Magnetic set of data available.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of zyxda in reg STATUS_REG.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_mag_data_ready_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_status_reg_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_STATUS_REG, (uint8_t*)&reg, 1);
+  *val = reg.zyxda;
+
+  return ret;
+}
+
+/**
+  * @brief  Magnetic set of data overrun.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of zyxor in reg STATUS_REG.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_mag_data_ovr_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_status_reg_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_STATUS_REG, (uint8_t*)&reg, 1);
+  *val = reg.zyxor;
+
+  return ret;
+}
+
+/**
+  * @brief  Magnetic output value.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  buff  that stores data read
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_magnetic_raw_get(lis2mdl_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_OUTX_L_REG, buff, 6);
+  return ret;
+}
+
+/**
+  * @brief  Temperature output value.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  buff  that stores data read
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_temperature_raw_get(lis2mdl_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_TEMP_OUT_L_REG, buff, 2);
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LIS2MDL_common
+  * @brief       This section group common usefull functions
+  * @{
+  *
+  */
+
+/**
+  * @brief  DeviceWhoamI.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  buff  that stores data read
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_device_id_get(lis2mdl_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_WHO_AM_I, buff, 1);
+  return ret;
+}
+
+/**
+  * @brief  Software reset. Restore the default values in user registers.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of soft_rst in reg CFG_REG_A
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_reset_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.soft_rst = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Software reset. Restore the default values in user registers.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of soft_rst in reg CFG_REG_A.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_reset_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  *val = reg.soft_rst;
+
+  return ret;
+}
+
+/**
+  * @brief  Reboot memory content. Reload the calibration parameters.[set] 
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of reboot in reg CFG_REG_A
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_boot_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.reboot = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Reboot memory content. Reload the calibration parameters.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of reboot in reg CFG_REG_A.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_boot_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_a_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_A, (uint8_t*)&reg, 1);
+  *val = reg.reboot;
+
+  return ret;
+}
+
+/**
+  * @brief  Selftest.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of self_test in reg CFG_REG_C
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_self_test_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.self_test = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Selftest.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of self_test in reg CFG_REG_C.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_self_test_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  *val = reg.self_test;
+
+  return ret;
+}
+
+/**
+  * @brief  Big/Little Endian data selection.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of ble in reg CFG_REG_C
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_data_format_set(lis2mdl_ctx_t *ctx, lis2mdl_ble_t val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.ble = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Big/Little Endian data selection.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of ble in reg CFG_REG_C.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_data_format_get(lis2mdl_ctx_t *ctx, lis2mdl_ble_t *val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  switch (reg.ble){
+    case LIS2MDL_LSB_AT_LOW_ADD:
+      *val = LIS2MDL_LSB_AT_LOW_ADD;
+      break;
+    case LIS2MDL_MSB_AT_LOW_ADD:
+      *val = LIS2MDL_MSB_AT_LOW_ADD;
+      break;
+    default:
+      *val = LIS2MDL_LSB_AT_LOW_ADD;
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  Info about device status.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   registers STATUS_REG.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_status_get(lis2mdl_ctx_t *ctx, lis2mdl_status_reg_t *val)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_STATUS_REG, (uint8_t*) val, 1);
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LIS2MDL_interrupts
+  * @brief       This section group all the functions that manage interrupts
+  * @{
+  *
+  */
+
+/**
+  * @brief  The interrupt block recognition checks data after/before the
+  *         hard-iron correction to discover the interrupt.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of int_on_dataoff in reg CFG_REG_B
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_offset_int_conf_set(lis2mdl_ctx_t *ctx,
+                                    lis2mdl_int_on_dataoff_t val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.int_on_dataoff = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  The interrupt block recognition checks data after/before the
+  *         hard-iron correction to discover the interrupt.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of int_on_dataoff in reg CFG_REG_B.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_offset_int_conf_get(lis2mdl_ctx_t *ctx,
+                                    lis2mdl_int_on_dataoff_t *val)
+{
+  lis2mdl_cfg_reg_b_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_B, (uint8_t*)&reg, 1);
+  switch (reg.int_on_dataoff){
+    case LIS2MDL_CHECK_BEFORE:
+      *val = LIS2MDL_CHECK_BEFORE;
+      break;
+    case LIS2MDL_CHECK_AFTER:
+      *val = LIS2MDL_CHECK_AFTER;
+      break;
+    default:
+      *val = LIS2MDL_CHECK_BEFORE;
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @brief  Data-ready signal on INT_DRDY pin.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of drdy_on_pin in reg CFG_REG_C
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_drdy_on_pin_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.drdy_on_pin = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Data-ready signal on INT_DRDY pin.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of drdy_on_pin in reg CFG_REG_C.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_drdy_on_pin_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  *val = reg.drdy_on_pin;
+
+  return ret;
+}
+
+/**
+  * @brief  Interrupt signal on INT_DRDY pin.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of int_on_pin in reg CFG_REG_C
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_int_on_pin_set(lis2mdl_ctx_t *ctx, uint8_t val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.int_on_pin = val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Interrupt signal on INT_DRDY pin.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of int_on_pin in reg CFG_REG_C.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_int_on_pin_get(lis2mdl_ctx_t *ctx, uint8_t *val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  *val = reg.int_on_pin;
+
+  return ret;
+}
+
+/**
+  * @brief  Interrupt generator configuration register.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   registers INT_CRTL_REG.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_int_gen_conf_set(lis2mdl_ctx_t *ctx,
+                                 lis2mdl_int_crtl_reg_t *val)
+{
+  int32_t ret;
+  ret = lis2mdl_write_reg(ctx, LIS2MDL_INT_CRTL_REG, (uint8_t*) val, 1);
+  return ret;
+}
+
+/**
+  * @brief  Interrupt generator configuration register.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   registers INT_CRTL_REG.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_int_gen_conf_get(lis2mdl_ctx_t *ctx,
+                                 lis2mdl_int_crtl_reg_t *val)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_INT_CRTL_REG, (uint8_t*) val, 1);
+  return ret;
+}
+
+/**
+  * @brief  Interrupt generator source register.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   registers INT_SOURCE_REG.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_int_gen_source_get(lis2mdl_ctx_t *ctx,
+                                   lis2mdl_int_source_reg_t *val)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_INT_SOURCE_REG, (uint8_t*) val, 1);
+  return ret;
+}
+
+/**
+  * @brief  User-defined threshold value for xl interrupt event on generator.
+  *         Data format is the same of output data raw: two’s complement with
+  *         1LSb = 1.5mG.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  buff  that contains data to write
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_int_gen_treshold_set(lis2mdl_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+  ret = lis2mdl_write_reg(ctx, LIS2MDL_INT_THS_L_REG, buff, 2);
+  return ret;
+}
+
+/**
+  * @brief  User-defined threshold value for xl interrupt event on generator.
+  *         Data format is the same of output data raw: two’s complement with
+  *         1LSb = 1.5mG.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  buff  that stores data read
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_int_gen_treshold_get(lis2mdl_ctx_t *ctx, uint8_t *buff)
+{
+  int32_t ret;
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_INT_THS_L_REG, buff, 2);
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/**
+  * @defgroup    LIS2MDL_serial_interface
+  * @brief       This section group all the functions concerning serial
+  *              interface management
+  * @{
+  *
+  */
+
+/**
+  * @brief  Enable/Disable I2C interface.[set]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   change the values of i2c_dis in reg CFG_REG_C
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_i2c_interface_set(lis2mdl_ctx_t *ctx, lis2mdl_i2c_dis_t val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  
+  if(ret == 0){
+    reg.i2c_dis = (uint8_t)val;
+    ret = lis2mdl_write_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  }
+  
+  return ret;
+}
+
+/**
+  * @brief  Enable/Disable I2C interface.[get]
+  *
+  * @param  ctx   read / write interface definitions.(ptr)
+  * @param  val   Get the values of i2c_dis in reg CFG_REG_C.(ptr)
+  * @retval       interface status.(MANDATORY: return 0 -> no Error)
+  *
+  */
+int32_t lis2mdl_i2c_interface_get(lis2mdl_ctx_t *ctx, lis2mdl_i2c_dis_t *val)
+{
+  lis2mdl_cfg_reg_c_t reg;
+  int32_t ret;
+
+  ret = lis2mdl_read_reg(ctx, LIS2MDL_CFG_REG_C, (uint8_t*)&reg, 1);
+  switch (reg.i2c_dis){
+    case LIS2MDL_I2C_ENABLE:
+      *val = LIS2MDL_I2C_ENABLE;
+      break;
+    case LIS2MDL_I2C_DISABLE:
+      *val = LIS2MDL_I2C_DISABLE;
+      break;
+    default:
+      *val = LIS2MDL_I2C_ENABLE;
+      break;
+  }
+  return ret;
+}
+
+/**
+  * @}
+  *
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lis2mdl_reg.h	Tue Mar 05 18:06:37 2019 +0000
@@ -0,0 +1,416 @@
+/*
+ ******************************************************************************
+ * @file    lis2mdl_reg.h
+ * @author  Sensors Software Solution Team
+ * @brief   This file contains all the functions prototypes for the
+ *          lis2mdl_reg.c driver.
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>&copy; COPYRIGHT(c) 2018 STMicroelectronics</center></h2>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   1. Redistributions of source code must retain the above copyright notice,
+ *      this list of conditions and the following disclaimer.
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *   3. Neither the name of STMicroelectronics nor the names of its
+ *      contributors may be used to endorse or promote products derived from
+ *      this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef LIS2MDL_REGS_H
+#define LIS2MDL_REGS_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include <stdint.h>
+#include <math.h>
+
+
+#ifndef float_t
+#define float_t float
+#endif
+
+/** @addtogroup LIS2MDL
+  * @{
+  *
+  */
+
+/** @defgroup LIS2MDL_sensors_common_types
+  * @{
+  *
+  */
+
+#ifndef MEMS_SHARED_TYPES
+#define MEMS_SHARED_TYPES
+
+/**
+  * @defgroup axisXbitXX_t
+  * @brief    These unions are useful to represent different sensors data type.
+  *           These unions are not need by the driver.
+  *
+  *           REMOVING the unions you are compliant with:
+  *           MISRA-C 2012 [Rule 19.2] -> " Union are not allowed "
+  *
+  * @{
+  *
+  */
+
+typedef union{
+  int16_t i16bit[3];
+  uint8_t u8bit[6];
+} axis3bit16_t;
+
+typedef union{
+  int16_t i16bit;
+  uint8_t u8bit[2];
+} axis1bit16_t;
+
+typedef union{
+  int32_t i32bit[3];
+  uint8_t u8bit[12];
+} axis3bit32_t;
+
+typedef union{
+  int32_t i32bit;
+  uint8_t u8bit[4];
+} axis1bit32_t;
+
+/**
+  * @}
+  *
+  */
+
+typedef struct{
+  uint8_t bit0       : 1;
+  uint8_t bit1       : 1;
+  uint8_t bit2       : 1;
+  uint8_t bit3       : 1;
+  uint8_t bit4       : 1;
+  uint8_t bit5       : 1;
+  uint8_t bit6       : 1;
+  uint8_t bit7       : 1;
+} bitwise_t;
+
+#define PROPERTY_DISABLE                (0U)
+#define PROPERTY_ENABLE                 (1U)
+
+#endif /* MEMS_SHARED_TYPES */
+
+/**
+  * @}
+  *
+  */
+
+  /** @addtogroup  LIS2MDL_Interfaces_Functions
+    * @brief       This section provide a set of functions used to read and
+    *              write a generic register of the device.
+    *              MANDATORY: return 0 -> no Error.
+    * @{
+    *
+    */
+
+typedef int32_t (*lis2mdl_write_ptr)(void *, uint8_t, uint8_t*, uint16_t);
+typedef int32_t (*lis2mdl_read_ptr) (void *, uint8_t, uint8_t*, uint16_t);
+
+typedef struct {
+  /** Component mandatory fields **/
+  lis2mdl_write_ptr  write_reg;
+  lis2mdl_read_ptr   read_reg;
+  /** Customizable optional pointer **/
+  void *handle;
+} lis2mdl_ctx_t;
+
+/**
+  * @}
+  *
+  */
+
+/** @defgroup LSM9DS1_Infos
+  * @{
+  *
+  */
+
+  /** I2C Device Address 8 bit format **/
+#define LIS2MDL_I2C_ADD                 0x3DU
+
+/** Device Identification (Who am I) **/
+#define LIS2MDL_ID                      0x40U
+
+/**
+  * @}
+  *
+  */
+
+#define LIS2MDL_OFFSET_X_REG_L          0x45U
+#define LIS2MDL_OFFSET_X_REG_H          0x46U
+#define LIS2MDL_OFFSET_Y_REG_L          0x47U
+#define LIS2MDL_OFFSET_Y_REG_H          0x48U
+#define LIS2MDL_OFFSET_Z_REG_L          0x49U
+#define LIS2MDL_OFFSET_Z_REG_H          0x4AU
+#define LIS2MDL_WHO_AM_I                0x4FU
+#define LIS2MDL_CFG_REG_A               0x60U
+typedef struct {
+  uint8_t md                     : 2;
+  uint8_t odr                    : 2;
+  uint8_t lp                     : 1;
+  uint8_t soft_rst               : 1;
+  uint8_t reboot                 : 1;
+  uint8_t comp_temp_en           : 1;
+} lis2mdl_cfg_reg_a_t;
+
+#define LIS2MDL_CFG_REG_B               0x61U
+typedef struct {
+  uint8_t lpf                    : 1;
+  uint8_t set_rst                : 2; /* OFF_CANC + Set_FREQ */
+  uint8_t int_on_dataoff         : 1;
+  uint8_t off_canc_one_shot      : 1;
+  uint8_t not_used_01            : 3;
+} lis2mdl_cfg_reg_b_t;
+
+#define LIS2MDL_CFG_REG_C               0x62U
+typedef struct {
+  uint8_t drdy_on_pin            : 1;
+  uint8_t self_test              : 1;
+  uint8_t not_used_01            : 1;
+  uint8_t ble                    : 1;
+  uint8_t bdu                    : 1;
+  uint8_t i2c_dis                : 1;
+  uint8_t int_on_pin             : 1;
+  uint8_t not_used_02            : 1;
+} lis2mdl_cfg_reg_c_t;
+
+#define LIS2MDL_INT_CRTL_REG            0x63U
+typedef struct {
+  uint8_t ien                    : 1;
+  uint8_t iel                    : 1;
+  uint8_t iea                    : 1;
+  uint8_t not_used_01            : 2;
+  uint8_t zien                   : 1;
+  uint8_t yien                   : 1;
+  uint8_t xien                   : 1;
+} lis2mdl_int_crtl_reg_t;
+
+#define LIS2MDL_INT_SOURCE_REG          0x64U
+typedef struct {
+  uint8_t _int                    : 1;
+  uint8_t mroi                   : 1;
+  uint8_t n_th_s_z               : 1;
+  uint8_t n_th_s_y               : 1;
+  uint8_t n_th_s_x               : 1;
+  uint8_t p_th_s_z               : 1;
+  uint8_t p_th_s_y               : 1;
+  uint8_t p_th_s_x               : 1;
+} lis2mdl_int_source_reg_t;
+
+#define LIS2MDL_INT_THS_L_REG           0x65U
+#define LIS2MDL_INT_THS_H_REG           0x66U
+#define LIS2MDL_STATUS_REG              0x67U
+typedef struct {
+  uint8_t xda                    : 1;
+  uint8_t yda                    : 1;
+  uint8_t zda                    : 1;
+  uint8_t zyxda                  : 1;
+  uint8_t xior                   : 1;  //changed as xor is a reserved word in c++
+  uint8_t yor                    : 1;
+  uint8_t zor                    : 1;
+  uint8_t zyxor                  : 1;
+} lis2mdl_status_reg_t;
+
+#define LIS2MDL_OUTX_L_REG              0x68U
+#define LIS2MDL_OUTX_H_REG              0x69U
+#define LIS2MDL_OUTY_L_REG              0x6AU
+#define LIS2MDL_OUTY_H_REG              0x6BU
+#define LIS2MDL_OUTZ_L_REG              0x6CU
+#define LIS2MDL_OUTZ_H_REG              0x6DU
+#define LIS2MDL_TEMP_OUT_L_REG          0x6EU
+#define LIS2MDL_TEMP_OUT_H_REG          0x6FU
+
+/**
+  * @defgroup LIS2MDL_Register_Union
+  * @brief    This union group all the registers that has a bit-field
+  *           description.
+  *           This union is useful but not need by the driver.
+  *
+  *           REMOVING this union you are compliant with:
+  *           MISRA-C 2012 [Rule 19.2] -> " Union are not allowed "
+  *
+  * @{
+  *
+  */
+typedef union{
+  lis2mdl_cfg_reg_a_t            cfg_reg_a;
+  lis2mdl_cfg_reg_b_t            cfg_reg_b;
+  lis2mdl_cfg_reg_c_t            cfg_reg_c;
+  lis2mdl_int_crtl_reg_t         int_crtl_reg;
+  lis2mdl_int_source_reg_t       int_source_reg;
+  lis2mdl_status_reg_t           status_reg;
+  bitwise_t                      bitwise;
+  uint8_t                        byte;
+} lis2mdl_reg_t;
+
+/**
+  * @}
+  *
+  */
+
+int32_t lis2mdl_read_reg(lis2mdl_ctx_t *ctx, uint8_t reg, uint8_t* data,
+                         uint16_t len);
+int32_t lis2mdl_write_reg(lis2mdl_ctx_t *ctx, uint8_t reg, uint8_t* data,
+                          uint16_t len);
+                          
+extern float_t lis2mdl_from_lsb_to_mgauss(int16_t lsb);
+extern float_t lis2mdl_from_lsb_to_celsius(int16_t lsb);
+
+int32_t lis2mdl_mag_user_offset_set(lis2mdl_ctx_t *ctx, uint8_t *buff);
+int32_t lis2mdl_mag_user_offset_get(lis2mdl_ctx_t *ctx, uint8_t *buff);
+
+typedef enum {
+  LIS2MDL_CONTINUOUS_MODE  = 0,
+  LIS2MDL_SINGLE_TRIGGER   = 1,
+  LIS2MDL_POWER_DOWN       = 2,
+} lis2mdl_md_t;
+int32_t lis2mdl_operating_mode_set(lis2mdl_ctx_t *ctx, lis2mdl_md_t val);
+int32_t lis2mdl_operating_mode_get(lis2mdl_ctx_t *ctx, lis2mdl_md_t *val);
+
+typedef enum {
+  LIS2MDL_ODR_10Hz   = 0,
+  LIS2MDL_ODR_20Hz   = 1,
+  LIS2MDL_ODR_50Hz   = 2,
+  LIS2MDL_ODR_100Hz  = 3,
+} lis2mdl_odr_t;
+int32_t lis2mdl_data_rate_set(lis2mdl_ctx_t *ctx, lis2mdl_odr_t val);
+int32_t lis2mdl_data_rate_get(lis2mdl_ctx_t *ctx, lis2mdl_odr_t *val);
+
+typedef enum {
+  LIS2MDL_HIGH_RESOLUTION  = 0,
+  LIS2MDL_LOW_POWER        = 1,
+} lis2mdl_lp_t;
+int32_t lis2mdl_power_mode_set(lis2mdl_ctx_t *ctx, lis2mdl_lp_t val);
+int32_t lis2mdl_power_mode_get(lis2mdl_ctx_t *ctx, lis2mdl_lp_t *val);
+
+int32_t lis2mdl_offset_temp_comp_set(lis2mdl_ctx_t *ctx, uint8_t val);
+int32_t lis2mdl_offset_temp_comp_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+typedef enum {
+  LIS2MDL_ODR_DIV_2  = 0,
+  LIS2MDL_ODR_DIV_4  = 1,
+} lis2mdl_lpf_t;
+int32_t lis2mdl_low_pass_bandwidth_set(lis2mdl_ctx_t *ctx,
+                                       lis2mdl_lpf_t val);
+int32_t lis2mdl_low_pass_bandwidth_get(lis2mdl_ctx_t *ctx,
+                                       lis2mdl_lpf_t *val);
+
+typedef enum {
+  LIS2MDL_SET_SENS_ODR_DIV_63        = 0,
+  LIS2MDL_SENS_OFF_CANC_EVERY_ODR    = 1,
+  LIS2MDL_SET_SENS_ONLY_AT_POWER_ON  = 2,
+} lis2mdl_set_rst_t;
+int32_t lis2mdl_set_rst_mode_set(lis2mdl_ctx_t *ctx,
+                                 lis2mdl_set_rst_t val);
+int32_t lis2mdl_set_rst_mode_get(lis2mdl_ctx_t *ctx,
+                                 lis2mdl_set_rst_t *val);
+
+int32_t lis2mdl_set_rst_sensor_single_set(lis2mdl_ctx_t *ctx,
+                                          uint8_t val);
+int32_t lis2mdl_set_rst_sensor_single_get(lis2mdl_ctx_t *ctx,
+                                          uint8_t *val);
+
+int32_t lis2mdl_block_data_update_set(lis2mdl_ctx_t *ctx, uint8_t val);
+int32_t lis2mdl_block_data_update_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+int32_t lis2mdl_mag_data_ready_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+int32_t lis2mdl_mag_data_ovr_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+int32_t lis2mdl_magnetic_raw_get(lis2mdl_ctx_t *ctx, uint8_t *buff);
+
+int32_t lis2mdl_temperature_raw_get(lis2mdl_ctx_t *ctx, uint8_t *buff);
+
+int32_t lis2mdl_device_id_get(lis2mdl_ctx_t *ctx, uint8_t *buff);
+
+int32_t lis2mdl_reset_set(lis2mdl_ctx_t *ctx, uint8_t val);
+int32_t lis2mdl_reset_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+int32_t lis2mdl_boot_set(lis2mdl_ctx_t *ctx, uint8_t val);
+int32_t lis2mdl_boot_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+int32_t lis2mdl_self_test_set(lis2mdl_ctx_t *ctx, uint8_t val);
+int32_t lis2mdl_self_test_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+typedef enum {
+  LIS2MDL_LSB_AT_LOW_ADD  = 0,
+  LIS2MDL_MSB_AT_LOW_ADD  = 1,
+} lis2mdl_ble_t;
+int32_t lis2mdl_data_format_set(lis2mdl_ctx_t *ctx, lis2mdl_ble_t val);
+int32_t lis2mdl_data_format_get(lis2mdl_ctx_t *ctx, lis2mdl_ble_t *val);
+
+int32_t lis2mdl_status_get(lis2mdl_ctx_t *ctx, lis2mdl_status_reg_t *val);
+
+typedef enum {
+  LIS2MDL_CHECK_BEFORE  = 0,
+  LIS2MDL_CHECK_AFTER   = 1,
+} lis2mdl_int_on_dataoff_t;
+int32_t lis2mdl_offset_int_conf_set(lis2mdl_ctx_t *ctx,
+                                    lis2mdl_int_on_dataoff_t val);
+int32_t lis2mdl_offset_int_conf_get(lis2mdl_ctx_t *ctx,
+                                    lis2mdl_int_on_dataoff_t *val);
+
+int32_t lis2mdl_drdy_on_pin_set(lis2mdl_ctx_t *ctx, uint8_t val);
+int32_t lis2mdl_drdy_on_pin_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+int32_t lis2mdl_int_on_pin_set(lis2mdl_ctx_t *ctx, uint8_t val);
+int32_t lis2mdl_int_on_pin_get(lis2mdl_ctx_t *ctx, uint8_t *val);
+
+int32_t lis2mdl_int_gen_conf_set(lis2mdl_ctx_t *ctx,
+                                 lis2mdl_int_crtl_reg_t *val);
+int32_t lis2mdl_int_gen_conf_get(lis2mdl_ctx_t *ctx,
+                                 lis2mdl_int_crtl_reg_t *val);
+
+int32_t lis2mdl_int_gen_source_get(lis2mdl_ctx_t *ctx,
+                                   lis2mdl_int_source_reg_t *val);
+
+int32_t lis2mdl_int_gen_treshold_set(lis2mdl_ctx_t *ctx, uint8_t *buff);
+int32_t lis2mdl_int_gen_treshold_get(lis2mdl_ctx_t *ctx, uint8_t *buff);
+
+typedef enum {
+  LIS2MDL_I2C_ENABLE   = 0,
+  LIS2MDL_I2C_DISABLE  = 1,
+} lis2mdl_i2c_dis_t;
+int32_t lis2mdl_i2c_interface_set(lis2mdl_ctx_t *ctx,
+                                  lis2mdl_i2c_dis_t val);
+int32_t lis2mdl_i2c_interface_get(lis2mdl_ctx_t *ctx,
+                                  lis2mdl_i2c_dis_t *val);
+
+/**
+  *@}
+  *
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIS2MDL_REGS_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/