diff --git a/components/lis2hh12/CMakeLists.txt b/components/lis2hh12/CMakeLists.txt new file mode 100644 index 00000000..ac05f1ee --- /dev/null +++ b/components/lis2hh12/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRCS lis2hh12.c + INCLUDE_DIRS . + REQUIRES i2cdev log esp_idf_lib_helpers +) diff --git a/components/lis2hh12/LICENSE b/components/lis2hh12/LICENSE new file mode 100644 index 00000000..0f499687 --- /dev/null +++ b/components/lis2hh12/LICENSE @@ -0,0 +1,30 @@ +BSD 3-Clause License + +Copyright (c) 2019, STMicroelectronics +Copyright (c) 2024, Ferdinand Keil +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* 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. + +* Neither the name of the copyright holder 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. diff --git a/components/lis2hh12/component.mk b/components/lis2hh12/component.mk new file mode 100644 index 00000000..a3610e86 --- /dev/null +++ b/components/lis2hh12/component.mk @@ -0,0 +1,2 @@ +COMPONENT_ADD_INCLUDEDIRS = . +COMPONENT_DEPENDS = i2cdev log esp_idf_lib_helpers diff --git a/components/lis2hh12/lis2hh12.c b/components/lis2hh12/lis2hh12.c new file mode 100644 index 00000000..0e3eb95a --- /dev/null +++ b/components/lis2hh12/lis2hh12.c @@ -0,0 +1,2664 @@ +/** + ****************************************************************************** + * @file lis2hh12.c + * @author Sensors Software Solution Team + * @brief LIS2HH12 driver file + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ +#include +#include +#include "lis2hh12.h" + +/** + * @defgroup LIS2HH12 + * @brief This file provides a set of functions needed to drive the + * lis2hh12 enhanced inertial module. + * @{ + * + */ + +#define I2C_FREQ_HZ 400000 + +#define CHECK_ARG(ARG) \ + do \ + { \ + if (!(ARG)) \ + return ESP_ERR_INVALID_ARG; \ + } \ + while (0) + +/** + * @defgroup LIS2HH12_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 dev I2C device to use + * @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 + * + */ +esp_err_t lis2hh12_read_reg(i2c_dev_t *dev, uint8_t reg, uint8_t *data, uint16_t len) +{ + CHECK_ARG(dev); + + esp_err_t ret; + + I2C_DEV_TAKE_MUTEX(dev); + ret = i2c_dev_read_reg(dev, reg, data, len); + I2C_DEV_GIVE_MUTEX(dev); + + return ret; +} + +/** + * @brief Write generic device register + * + * @param dev I2C device to use + * @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 + * + */ +esp_err_t lis2hh12_write_reg(i2c_dev_t *dev, uint8_t reg, uint8_t *data, uint16_t len) +{ + CHECK_ARG(dev); + + esp_err_t ret; + + I2C_DEV_TAKE_MUTEX(dev); + ret = i2c_dev_write_reg(dev, reg, data, len); + I2C_DEV_GIVE_MUTEX(dev); + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Sensitivity + * @brief These functions convert raw-data into engineering units. + * @{ + * + */ + +float_t lis2hh12_from_fs2g_to_mg(int16_t lsb) +{ + return ((float_t)lsb * 0.061f); +} + +float_t lis2hh12_from_fs4g_to_mg(int16_t lsb) +{ + return ((float_t)lsb * 0.122f); +} + +float_t lis2hh12_from_fs8g_to_mg(int16_t lsb) +{ + return ((float_t)lsb * 0.244f); +} + +float_t lis2hh12_from_lsb_to_celsius(int16_t lsb) +{ + /* 8 LSB/C - 11bit resolution */ + return ((((float_t)lsb / 32.0f) / 8.0f) + 25.0f); +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Data_generation + * @brief This section groups all the functions concerning + * data generation + * @{ + * + */ + +/** + * @brief Enable accelerometer axis.[set] + * + * @param dev I2C device to use + * @param val Accelerometer’s X-axis output enable. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_axis_set(i2c_dev_t *dev, lis2hh12_xl_axis_t val) +{ + lis2hh12_ctrl1_t ctrl1; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret == ESP_OK) + { + ctrl1.xen = val.xen; + ctrl1.yen = val.yen; + ctrl1.zen = val.zen; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + } + + return ret; +} + +/** + * @brief Enable accelerometer axis.[get] + * + * @param dev I2C device to use + * @param val Accelerometer’s X-axis output enable.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_axis_get(i2c_dev_t *dev, lis2hh12_xl_axis_t *val) +{ + lis2hh12_ctrl1_t ctrl1; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret == ESP_OK) + { + val->xen = ctrl1.xen; + val->yen = ctrl1.yen; + val->zen = ctrl1.zen; + } + + return ret; +} + +/** + * @brief Blockdataupdate.[set] + * + * @param dev I2C device to use + * @param val Change the values of bdu in reg CTRL1. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_block_data_update_set(i2c_dev_t *dev, uint8_t val) +{ + lis2hh12_ctrl1_t ctrl1; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret == ESP_OK) + { + ctrl1.bdu = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + } + + return ret; +} + +/** + * @brief Blockdataupdate.[get] + * + * @param dev I2C device to use + * @param val Get the values of bdu in reg CTRL1.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_block_data_update_get(i2c_dev_t *dev, uint8_t *val) +{ + lis2hh12_ctrl1_t ctrl1; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret == ESP_OK) + { + *val = (uint8_t)ctrl1.bdu; + } + + return ret; +} + +/** + * @brief Accelerometer data rate selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of "odr" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_data_rate_set(i2c_dev_t *dev, lis2hh12_xl_data_rate_t val) +{ + lis2hh12_ctrl1_t ctrl1; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret == ESP_OK) + { + ctrl1.odr = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + } + + return ret; +} + +/** + * @brief Accelerometer data rate selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of odr in reg CTRL1.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_data_rate_get(i2c_dev_t *dev, lis2hh12_xl_data_rate_t *val) +{ + lis2hh12_ctrl1_t ctrl1; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl1.odr) + { + case LIS2HH12_XL_ODR_OFF: + *val = LIS2HH12_XL_ODR_OFF; + break; + + case LIS2HH12_XL_ODR_10Hz: + *val = LIS2HH12_XL_ODR_10Hz; + break; + + case LIS2HH12_XL_ODR_50Hz: + *val = LIS2HH12_XL_ODR_50Hz; + break; + + case LIS2HH12_XL_ODR_100Hz: + *val = LIS2HH12_XL_ODR_100Hz; + break; + + case LIS2HH12_XL_ODR_200Hz: + *val = LIS2HH12_XL_ODR_200Hz; + break; + + case LIS2HH12_XL_ODR_400Hz: + *val = LIS2HH12_XL_ODR_400Hz; + break; + + case LIS2HH12_XL_ODR_800Hz: + *val = LIS2HH12_XL_ODR_800Hz; + break; + + default: + *val = LIS2HH12_XL_ODR_OFF; + break; + } + + return ret; +} + +/** + * @brief Accelerometer full-scale selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of "fs" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_full_scale_set(i2c_dev_t *dev, lis2hh12_xl_fs_t val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret == ESP_OK) + { + ctrl4.fs = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + } + + return ret; +} + +/** + * @brief Accelerometer full-scale selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of fs in reg CTRL4.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_full_scale_get(i2c_dev_t *dev, lis2hh12_xl_fs_t *val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl4.fs) + { + case LIS2HH12_2g: + *val = LIS2HH12_2g; + break; + + case LIS2HH12_4g: + *val = LIS2HH12_4g; + break; + + case LIS2HH12_8g: + *val = LIS2HH12_8g; + break; + + default: + *val = LIS2HH12_2g; + break; + } + + return ret; +} + +/** + * @brief Decimation of acceleration data on OUT REG and FIFO.[set] + * + * @param dev I2C device to use + * @param val Change the values of "dec" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_decimation_set(i2c_dev_t *dev, lis2hh12_dec_t val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret == ESP_OK) + { + ctrl5.dec = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + } + + return ret; +} + +/** + * @brief Decimation of acceleration data on OUT REG and FIFO.[get] + * + * @param dev I2C device to use + * @param val Get the values of dec in reg CTRL5.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_decimation_get(i2c_dev_t *dev, lis2hh12_dec_t *val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl5.dec) + { + case LIS2HH12_NO_DECIMATION: + *val = LIS2HH12_NO_DECIMATION; + break; + + case LIS2HH12_EVERY_2_SAMPLES: + *val = LIS2HH12_EVERY_2_SAMPLES; + break; + + case LIS2HH12_EVERY_4_SAMPLES: + *val = LIS2HH12_EVERY_4_SAMPLES; + break; + + case LIS2HH12_EVERY_8_SAMPLES: + *val = LIS2HH12_EVERY_8_SAMPLES; + break; + + default: + *val = LIS2HH12_NO_DECIMATION; + break; + } + + return ret; +} + +/** + * @brief New data available.[get] + * + * @param dev I2C device to use + * @param val Iet the values of "zyxda" in reg STATUS.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_flag_data_ready_get(i2c_dev_t *dev, uint8_t *val) +{ + lis2hh12_status_t status; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_STATUS, (uint8_t *)&status, 1); + + if (ret == ESP_OK) + { + *val = status.zyxda; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Dataoutput + * @brief This section groups all the data output functions. + * @{ + * + */ + +/** + * @brief Temperature data output register (r). L and H registers together + * express a 16-bit word in two’s complement.[get] + * + * @param dev I2C device to use + * @param buff Buffer that stores the data read.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_temperature_raw_get(i2c_dev_t *dev, int16_t *val) +{ + uint8_t buff[2]; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_TEMP_L, buff, 2); + + if (ret == ESP_OK) + { + *val = (int16_t)buff[1]; + *val = (*val * 256) + (int16_t)buff[0]; + } + + return ret; +} + +/** + * @brief Linear acceleration output register. The value is expressed + * as a 16-bit word in two’s complement.[get] + * + * @param dev I2C device to use + * @param buff Buffer that stores the data read.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_acceleration_raw_get(i2c_dev_t *dev, int16_t *val) +{ + uint8_t buff[6]; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_OUT_X_L, buff, 6); + + if (ret == ESP_OK) + { + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Common + * @brief This section groups common useful functions. + * @{ + * + */ + +/** + * @brief Initialize device descriptor + * + * @param dev Device descriptor + * @param port I2C port + * @param sda_gpio SDA GPIO + * @param scl_gpio SCL GPIO + * @retval `ESP_OK` on success + */ +esp_err_t lis2hh12_init_desc(i2c_dev_t *dev, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio, bool pin_sa0) +{ + CHECK_ARG(dev); + + dev->port = port; + dev->addr = pin_sa0 ? LIS2HH12_ADDR_SA0_H : LIS2HH12_ADDR_SA0_L; + dev->cfg.sda_io_num = sda_gpio; + dev->cfg.scl_io_num = scl_gpio; +#if HELPER_TARGET_IS_ESP32 + dev->cfg.master.clk_speed = I2C_FREQ_HZ; +#endif + return i2c_dev_create_mutex(dev); +} + +/** + * @brief Free device descriptor + * + * @param dev Device descriptor + * @return `ESP_OK` on success + */ +esp_err_t lis2hh12_free_desc(i2c_dev_t *dev) +{ + CHECK_ARG(dev); + + return i2c_dev_delete_mutex(dev); +} + +/** + * @brief DeviceWhoamI.[get] + * + * @param dev I2C device to use + * @param buff Buffer that stores the data read.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_dev_id_get(i2c_dev_t *dev, uint8_t *buff) +{ + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_WHO_AM_I, buff, 1); + + return ret; +} + +/** + * @brief Software reset. Restore the default values + * in user registers.[set] + * + * @param dev I2C device to use + * @param val Change the values of soft_reset in reg CTRL5. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_dev_reset_set(i2c_dev_t *dev, uint8_t val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret == ESP_OK) + { + ctrl5.soft_reset = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + } + + return ret; +} + +/** + * @brief Software reset. Restore the default values in + * user registers.[get] + * + * @param dev I2C device to use + * @param val Get the values of soft_reset in reg CTRL5.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_dev_reset_get(i2c_dev_t *dev, uint8_t *val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret == ESP_OK) + { + *val = (uint8_t)ctrl5.soft_reset; + } + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[set] + * + * @param dev I2C device to use + * @param val Change the values of boot in reg CTRL6. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_dev_boot_set(i2c_dev_t *dev, uint8_t val) +{ + lis2hh12_ctrl6_t ctrl6; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL6, (uint8_t *)&ctrl6, 1); + + if (ret == ESP_OK) + { + ctrl6.boot = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL6, (uint8_t *)&ctrl6, 1); + } + + return ret; +} + +/** + * @brief Reboot memory content. Reload the calibration parameters.[get] + * + * @param dev I2C device to use + * @param val Get the values of boot in reg CTRL6.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_dev_boot_get(i2c_dev_t *dev, uint8_t *val) +{ + lis2hh12_ctrl6_t ctrl6; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL6, (uint8_t *)&ctrl6, 1); + + if (ret == ESP_OK) + { + *val = (uint8_t)ctrl6.boot; + } + + return ret; +} + +/** + * @brief Device status register.[get] + * + * @param dev I2C device to use + * @param val X-axis new data available.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_dev_status_get(i2c_dev_t *dev, lis2hh12_status_reg_t *val) +{ + lis2hh12_status_t status; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_STATUS, (uint8_t *)&status, 1); + + if (ret == ESP_OK) + { + val->xda = status.xda; + val->yda = status.yda; + val->zda = status.zda; + val->zyxda = status.zyxda; + val->_xor = status._xor; + val->yor = status.yor; + val->zor = status.zor; + val->zyxor = status.zyxor; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Filters + * @brief This section group all the functions concerning the + * filters configuration + * @{ + * + */ + +/** + * @brief Accelerometer filter routing on interrupt generators.[set] + * + * @param dev I2C device to use + * @param val Change the values of "hpis" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_int_path_set(i2c_dev_t *dev, lis2hh12_xl_hp_path_t val) +{ + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + + if (ret == ESP_OK) + { + ctrl2.hpis = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + } + + return ret; +} + +/** + * @brief Accelerometer filter routing on interrupt generators.[get] + * + * @param dev I2C device to use + * @param val Get the values of hpis in reg CTRL2.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_int_path_get(i2c_dev_t *dev, lis2hh12_xl_hp_path_t *val) +{ + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl2.hpis) + { + case LIS2HH12_HP_DISABLE: + *val = LIS2HH12_HP_DISABLE; + break; + + case LIS2HH12_HP_ON_INT_GEN_1: + *val = LIS2HH12_HP_ON_INT_GEN_1; + break; + + case LIS2HH12_HP_ON_INT_GEN_2: + *val = LIS2HH12_HP_ON_INT_GEN_2; + break; + + default: + *val = LIS2HH12_HP_DISABLE; + break; + } + + return ret; +} + +/** + * @brief Accelerometer output filter path configuration.[set] + * + * @param dev I2C device to use + * @param val Change the values of "fds" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_out_path_set(i2c_dev_t *dev, lis2hh12_xl_out_path_t val) +{ + lis2hh12_ctrl1_t ctrl1; + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret == ESP_OK) + { + ctrl1.hr = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + } + + if (ret == ESP_OK) + { + ctrl2.fds = ((uint8_t)val & 0x02U) >> 1; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + } + + return ret; +} + +/** + * @brief Accelerometer output filter path configuration.[get] + * + * @param dev I2C device to use + * @param val Get the values of fds in reg CTRL2.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_out_path_get(i2c_dev_t *dev, lis2hh12_xl_out_path_t *val) +{ + lis2hh12_ctrl1_t ctrl1; + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL1, (uint8_t *)&ctrl1, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch ((ctrl2.fds << 1) | ctrl1.hr) + { + case LIS2HH12_BYPASSED: + *val = LIS2HH12_BYPASSED; + break; + + case LIS2HH12_FILT_HP: + *val = LIS2HH12_FILT_HP; + break; + + case LIS2HH12_FILT_LP: + *val = LIS2HH12_FILT_LP; + break; + + default: + *val = LIS2HH12_BYPASSED; + break; + } + } + + return ret; +} + +/** + * @brief Accelerometer digital filter high pass cutoff + * frequency selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of "hpm" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_hp_bandwidth_set(i2c_dev_t *dev, lis2hh12_xl_hp_bw_t val) +{ + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + + if (ret == ESP_OK) + { + ctrl2.hpm = (uint8_t)val & 0x01U; + ctrl2.dfc = (((uint8_t)val & 0x30U) >> 4); + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + } + + return ret; +} + +/** + * @brief Accelerometer digital filter high pass cutoff frequency + * selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of hpm in reg CTRL2.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_hp_bandwidth_get(i2c_dev_t *dev, lis2hh12_xl_hp_bw_t *val) +{ + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch ((ctrl2.dfc << 4) | ctrl2.hpm) + { + case LIS2HH12_HP_ODR_DIV_50: + *val = LIS2HH12_HP_ODR_DIV_50; + break; + + case LIS2HH12_HP_ODR_DIV_100: + *val = LIS2HH12_HP_ODR_DIV_100; + break; + + case LIS2HH12_HP_ODR_DIV_9: + *val = LIS2HH12_HP_ODR_DIV_9; + break; + + case LIS2HH12_HP_ODR_DIV_400: + *val = LIS2HH12_HP_ODR_DIV_400; + break; + + case LIS2HH12_HP_ODR_DIV_50_REF_MD: + *val = LIS2HH12_HP_ODR_DIV_50_REF_MD; + break; + + case LIS2HH12_HP_ODR_DIV_100_REF_MD: + *val = LIS2HH12_HP_ODR_DIV_100_REF_MD; + break; + + case LIS2HH12_HP_ODR_DIV_9_REF_MD: + *val = LIS2HH12_HP_ODR_DIV_9_REF_MD; + break; + + case LIS2HH12_HP_ODR_DIV_400_REF_MD: + *val = LIS2HH12_HP_ODR_DIV_400_REF_MD; + break; + + default: + *val = LIS2HH12_HP_ODR_DIV_50; + break; + } + + return ret; +} + +/** + * @brief Accelerometer digital filter low pass cutoff frequency + * selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of "dfc" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_low_bandwidth_set(i2c_dev_t *dev, lis2hh12_xl_lp_bw_t val) +{ + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + + if (ret == ESP_OK) + { + ctrl2.dfc = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + } + + return ret; +} + +/** + * @brief Accelerometer digital filter low pass cutoff frequency + * selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of dfc in reg CTRL2.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_low_bandwidth_get(i2c_dev_t *dev, lis2hh12_xl_lp_bw_t *val) +{ + lis2hh12_ctrl2_t ctrl2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL2, (uint8_t *)&ctrl2, 1); + + if (ret != ESP_OK) + { + return ret; + } + switch (ctrl2.dfc) + { + case LIS2HH12_LP_ODR_DIV_50: + *val = LIS2HH12_LP_ODR_DIV_50; + break; + + case LIS2HH12_LP_ODR_DIV_100: + *val = LIS2HH12_LP_ODR_DIV_100; + break; + + case LIS2HH12_LP_ODR_DIV_9: + *val = LIS2HH12_LP_ODR_DIV_9; + break; + + case LIS2HH12_LP_ODR_DIV_400: + *val = LIS2HH12_LP_ODR_DIV_400; + break; + + default: + *val = LIS2HH12_LP_ODR_DIV_50; + break; + } + + return ret; +} + +/** + * @brief Set anti-aliasing filter bandwidth.[set] + * + * @param dev I2C device to use + * @param val Change the values of "bw_scale_odr" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_aalias_bandwidth_set(i2c_dev_t *dev, lis2hh12_xl_filt_aa_bw_t val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret == ESP_OK) + { + ctrl4.bw_scale_odr = (((uint8_t)val & 0x10U) >> 4); + ctrl4.bw = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + } + + return ret; +} + +/** + * @brief Set anti-aliasing filter bandwidth.[get] + * + * @param dev I2C device to use + * @param val Get the values of bw_scale_odr in reg CTRL4.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_aalias_bandwidth_get(i2c_dev_t *dev, lis2hh12_xl_filt_aa_bw_t *val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch ((ctrl4.bw_scale_odr << 4) | ctrl4.bw) + { + case LIS2HH12_AUTO: + *val = LIS2HH12_AUTO; + break; + + case LIS2HH12_408Hz: + *val = LIS2HH12_408Hz; + break; + + case LIS2HH12_211Hz: + *val = LIS2HH12_211Hz; + break; + + case LIS2HH12_105Hz: + *val = LIS2HH12_105Hz; + break; + + case LIS2HH12_50Hz: + *val = LIS2HH12_50Hz; + break; + + default: + *val = LIS2HH12_AUTO; + break; + } + + return ret; +} + +/** + * @brief Reference value for acelerometer digital high-pass filter.[set] + * + * @param dev I2C device to use + * @param buff Buffer that stores data to be write.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_reference_set(i2c_dev_t *dev, int16_t *val) +{ + uint8_t buff[6]; + esp_err_t ret; + + buff[1] = (uint8_t)((uint16_t)val[0] / 256U); + buff[0] = (uint8_t)((uint16_t)val[0] - (buff[1] * 256U)); + buff[3] = (uint8_t)((uint16_t)val[1] / 256U); + buff[2] = (uint8_t)((uint16_t)val[1] - (buff[3] * 256U)); + buff[5] = (uint8_t)((uint16_t)val[2] / 256U); + buff[4] = (uint8_t)((uint16_t)val[2] - (buff[5] * 256U)); + ret = lis2hh12_write_reg(dev, LIS2HH12_XL_REFERENCE, buff, 6); + + return ret; +} + +/** + * @brief Reference value for acelerometer digital high-pass filter.[get] + * + * @param dev I2C device to use + * @param buff Buffer that stores data read.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_filter_reference_get(i2c_dev_t *dev, int16_t *val) +{ + uint8_t buff[6]; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_XL_REFERENCE, buff, 6); + val[0] = (int16_t)buff[1]; + val[0] = (val[0] * 256) + (int16_t)buff[0]; + val[1] = (int16_t)buff[3]; + val[1] = (val[1] * 256) + (int16_t)buff[2]; + val[2] = (int16_t)buff[5]; + val[2] = (val[2] * 256) + (int16_t)buff[4]; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Serial_interface + * @brief This section groups all the functions concerning main + * serial interface management (not auxiliary) + * @{ + * + */ + +/** + * @brief SPI Serial Interface Mode selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of "sim" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_spi_mode_set(i2c_dev_t *dev, lis2hh12_sim_t val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret == ESP_OK) + { + ctrl4.sim = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + } + + return ret; +} + +/** + * @brief SPI Serial Interface Mode selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of sim in reg CTRL4.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_spi_mode_get(i2c_dev_t *dev, lis2hh12_sim_t *val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl4.sim) + { + case LIS2HH12_SPI_4_WIRE: + *val = LIS2HH12_SPI_4_WIRE; + break; + + case LIS2HH12_SPI_3_WIRE: + *val = LIS2HH12_SPI_3_WIRE; + break; + + default: + *val = LIS2HH12_SPI_4_WIRE; + break; + } + + return ret; +} + +/** + * @brief Disable I2C interface.[set] + * + * @param dev I2C device to use + * @param val Change the values of "i2c_disable" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_i2c_interface_set(i2c_dev_t *dev, lis2hh12_i2c_dis_t val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret == ESP_OK) + { + ctrl4.i2c_disable = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + } + + return ret; +} + +/** + * @brief Disable I2C interface.[get] + * + * @param dev I2C device to use + * @param val Get the values of i2c_disable in reg CTRL4.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_i2c_interface_get(i2c_dev_t *dev, lis2hh12_i2c_dis_t *val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl4.i2c_disable) + { + case LIS2HH12_I2C_ENABLE: + *val = LIS2HH12_I2C_ENABLE; + break; + + case LIS2HH12_I2C_DISABLE: + *val = LIS2HH12_I2C_DISABLE; + break; + + default: + *val = LIS2HH12_I2C_ENABLE; + break; + } + + return ret; +} + +/** + * @brief Register address automatically incremented during a + * multiple byte access with a serial interface.[set] + * + * @param dev I2C device to use + * @param val Change the values of "if_add_inc" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_auto_increment_set(i2c_dev_t *dev, lis2hh12_auto_inc_t val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret == ESP_OK) + { + ctrl4.if_add_inc = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + } + + return ret; +} + +/** + * @brief Register address automatically incremented during a multiple + * byte access with a serial interface.[get] + * + * @param dev I2C device to use + * @param val Get the values of if_add_inc in reg CTRL4.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_auto_increment_get(i2c_dev_t *dev, lis2hh12_auto_inc_t *val) +{ + lis2hh12_ctrl4_t ctrl4; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL4, (uint8_t *)&ctrl4, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl4.if_add_inc) + { + case LIS2HH12_DISABLE: + *val = LIS2HH12_DISABLE; + break; + + case LIS2HH12_ENABLE: + *val = LIS2HH12_ENABLE; + break; + + default: + *val = LIS2HH12_DISABLE; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Interrupt_pins + * @brief This section groups all the functions that manage + * interrupt pins + * @{ + * + */ + +/** + * @brief Route a signal on INT 1 pin.[set] + * + * @param dev I2C device to use + * @param val Accelerometer data ready on INT 1 pin. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_int1_route_set(i2c_dev_t *dev, lis2hh12_pin_int1_route_t val) +{ + lis2hh12_ctrl3_t ctrl3; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + + if (ret == ESP_OK) + { + ctrl3.int1_drdy = val.int1_drdy; + ctrl3.int1_fth = val.int1_fth; + ctrl3.int1_ovr = val.int1_ovr; + ctrl3.int1_ig1 = val.int1_ig1; + ctrl3.int1_ig2 = val.int1_ig2; + ctrl3.int1_inact = val.int1_inact; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + } + + return ret; +} + +/** + * @brief Route a signal on INT 1 pin.[get] + * + * @param dev I2C device to use + * @param val Accelerometer data ready on INT 1 pin.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_int1_route_get(i2c_dev_t *dev, lis2hh12_pin_int1_route_t *val) +{ + lis2hh12_ctrl3_t ctrl3; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + + if (ret != ESP_OK) + { + return ret; + } + + val->int1_drdy = ctrl3.int1_drdy; + val->int1_fth = ctrl3.int1_fth; + val->int1_ovr = ctrl3.int1_ovr; + val->int1_ig1 = ctrl3.int1_ig1; + val->int1_ig2 = ctrl3.int1_ig2; + val->int1_inact = ctrl3.int1_inact; + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[set] + * + * @param dev I2C device to use + * @param val Change the values of "pp_od" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_mode_set(i2c_dev_t *dev, lis2hh12_pp_od_t val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret == ESP_OK) + { + ctrl5.pp_od = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + } + + return ret; +} + +/** + * @brief Push-pull/open drain selection on interrupt pads.[get] + * + * @param dev I2C device to use + * @param val Get the values of pp_od in reg CTRL5.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_mode_get(i2c_dev_t *dev, lis2hh12_pp_od_t *val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl5.pp_od) + { + case LIS2HH12_PUSH_PULL: + *val = LIS2HH12_PUSH_PULL; + break; + + case LIS2HH12_OPEN_DRAIN: + *val = LIS2HH12_OPEN_DRAIN; + break; + + default: + *val = LIS2HH12_PUSH_PULL; + break; + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.Interrupt active-high/low.[set] + * + * @param dev I2C device to use + * @param val Change the values of "h_lactive" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_polarity_set(i2c_dev_t *dev, lis2hh12_pin_pol_t val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret == ESP_OK) + { + ctrl5.h_lactive = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + } + + return ret; +} + +/** + * @brief Interrupt active-high/low.Interrupt active-high/low.[get] + * + * @param dev I2C device to use + * @param val Get the values of h_lactive in reg CTRL5.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_polarity_get(i2c_dev_t *dev, lis2hh12_pin_pol_t *val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl5.h_lactive) + { + case LIS2HH12_ACTIVE_HIGH: + *val = LIS2HH12_ACTIVE_HIGH; + break; + + case LIS2HH12_ACTIVE_LOW: + *val = LIS2HH12_ACTIVE_LOW; + break; + + default: + *val = LIS2HH12_ACTIVE_HIGH; + break; + } + + return ret; +} + +/** + * @brief Route a signal on INT 2 pin.[set] + * + * @param dev I2C device to use + * @param val Accelerometer data ready on INT2 pin. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_int2_route_set(i2c_dev_t *dev, lis2hh12_pin_int2_route_t val) +{ + lis2hh12_ctrl6_t ctrl6; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL6, (uint8_t *)&ctrl6, 1); + + if (ret == ESP_OK) + { + ctrl6.int2_drdy = val.int2_drdy; + ctrl6.int2_fth = val.int2_fth; + ctrl6.int2_empty = val.int2_empty; + ctrl6.int2_ig1 = val.int2_ig1; + ctrl6.int2_ig2 = val.int2_ig2; + ctrl6.int2_boot = val.int2_boot; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL6, (uint8_t *)&ctrl6, 1); + } + + return ret; +} + +/** + * @brief Route a signal on INT 2 pin.[get] + * + * @param dev I2C device to use + * @param val Accelerometer data ready on INT2 pin.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_int2_route_get(i2c_dev_t *dev, lis2hh12_pin_int2_route_t *val) +{ + lis2hh12_ctrl6_t ctrl6; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL6, (uint8_t *)&ctrl6, 1); + + if (ret != ESP_OK) + { + return ret; + } + + val->int2_drdy = ctrl6.int2_drdy; + val->int2_fth = ctrl6.int2_fth; + val->int2_empty = ctrl6.int2_empty; + val->int2_ig1 = ctrl6.int2_ig1; + val->int2_ig2 = ctrl6.int2_ig2; + val->int2_boot = ctrl6.int2_boot; + + return ret; +} + +/** + * @brief Latched/pulsed interrupt.[set] + * + * @param dev I2C device to use + * @param val Change the values of "lir" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_notification_set(i2c_dev_t *dev, lis2hh12_lir_t val) +{ + lis2hh12_ctrl7_t ctrl7; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + + if (ret == ESP_OK) + { + ctrl7.lir = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + } + + return ret; +} + +/** + * @brief Latched/pulsed interrupt.[get] + * + * @param dev I2C device to use + * @param val Get the values of lir in reg CTRL7.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_notification_get(i2c_dev_t *dev, lis2hh12_lir_t *val) +{ + lis2hh12_ctrl7_t ctrl7; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl7.lir) + { + case LIS2HH12_INT_PULSED: + *val = LIS2HH12_INT_PULSED; + break; + + case LIS2HH12_INT_LATCHED: + *val = LIS2HH12_INT_LATCHED; + break; + + default: + *val = LIS2HH12_INT_PULSED; + break; + } + + return ret; +} + +/** + * @brief AND/OR combination of accelerometer’s interrupt events.[set] + * + * @param dev I2C device to use + * @param val Change the values of "aoi" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_logic_set(i2c_dev_t *dev, lis2hh12_pin_logic_t val) +{ + lis2hh12_ig_cfg1_t ig_cfg1; + lis2hh12_ig_cfg2_t ig_cfg2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + + if (ret == ESP_OK) + { + ig_cfg1.aoi = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + if (ret == ESP_OK) + { + ig_cfg2.aoi = (((uint8_t)val & 0x02U) >> 1); + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + return ret; +} + +/** + * @brief AND/OR combination of accelerometer’s interrupt events.[get] + * + * @param dev I2C device to use + * @param val Get the values of aoi in reg IG_CFG1.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_pin_logic_get(i2c_dev_t *dev, lis2hh12_pin_logic_t *val) +{ + lis2hh12_ig_cfg1_t ig_cfg1; + lis2hh12_ig_cfg2_t ig_cfg2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + switch ((ig_cfg2.aoi << 1) | ig_cfg1.aoi) + { + case LIS2HH12_IG1_OR_IG2_OR: + *val = LIS2HH12_IG1_OR_IG2_OR; + break; + + case LIS2HH12_IG1_AND_IG2_OR: + *val = LIS2HH12_IG1_AND_IG2_OR; + break; + + case LIS2HH12_IG1_OR_IG2_AND: + *val = LIS2HH12_IG1_OR_IG2_AND; + break; + + case LIS2HH12_IG1_AND_IG2_AND: + *val = LIS2HH12_IG1_AND_IG2_AND; + break; + + default: + *val = LIS2HH12_IG1_OR_IG2_OR; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Interrupt_on_threshold + * @brief This section group all the functions concerning the + * interrupt on threshold configuration + * @{ + * + */ + +/** + * @brief Decrement or reset counter mode selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of "dcrm" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_mode_set(i2c_dev_t *dev, lis2hh12_dcrm_t val) +{ + lis2hh12_ctrl7_t ctrl7; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + + if (ret == ESP_OK) + { + ctrl7.dcrm = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + } + + return ret; +} + +/** + * @brief Decrement or reset counter mode selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of dcrm in reg CTRL7.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_mode_get(i2c_dev_t *dev, lis2hh12_dcrm_t *val) +{ + lis2hh12_ctrl7_t ctrl7; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl7.dcrm) + { + case LIS2HH12_RESET_MODE: + *val = LIS2HH12_RESET_MODE; + break; + + case LIS2HH12_DECREMENT_MODE: + *val = LIS2HH12_DECREMENT_MODE; + break; + + default: + *val = LIS2HH12_RESET_MODE; + break; + } + + return ret; +} + +/** + * @brief Enable interrupt generation on threshold event.[set] + * + * @param dev I2C device to use + * @param val Enable interrupt generation on accelerometer’s + * X-axis low event. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_axis_set(i2c_dev_t *dev, lis2hh12_xl_trshld_en_t val) +{ + lis2hh12_ig_cfg1_t ig_cfg1; + lis2hh12_ig_cfg2_t ig_cfg2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + + if (ret == ESP_OK) + { + ig_cfg1.xlie = (uint8_t)val.ig1_xlie; + ig_cfg1.xhie = (uint8_t)val.ig1_xhie; + ig_cfg1.ylie = (uint8_t)val.ig1_ylie; + ig_cfg1.yhie = (uint8_t)val.ig1_yhie; + ig_cfg1.zlie = (uint8_t)val.ig1_zlie; + ig_cfg1.zhie = (uint8_t)val.ig1_zhie; + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + if (ret == ESP_OK) + { + ig_cfg2.xlie = (uint8_t)val.ig2_xlie; + ig_cfg2.xhie = (uint8_t)val.ig2_xhie; + ig_cfg2.ylie = (uint8_t)val.ig2_ylie; + ig_cfg2.yhie = (uint8_t)val.ig2_yhie; + ig_cfg2.zlie = (uint8_t)val.ig2_zlie; + ig_cfg2.zhie = (uint8_t)val.ig2_zhie; + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + return ret; +} + +/** + * @brief Enable interrupt generation on threshold event.[get] + * + * @param dev I2C device to use + * @param val Enable interrupt generation on accelerometer’s + * X-axis low event.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_axis_get(i2c_dev_t *dev, lis2hh12_xl_trshld_en_t *val) +{ + lis2hh12_ig_cfg1_t ig_cfg1; + lis2hh12_ig_cfg2_t ig_cfg2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + val->ig1_xlie = ig_cfg1.xlie; + val->ig1_xhie = ig_cfg1.xhie; + val->ig1_ylie = ig_cfg1.ylie; + val->ig1_yhie = ig_cfg1.yhie; + val->ig1_zlie = ig_cfg1.zlie; + val->ig1_zhie = ig_cfg1.zhie; + val->ig2_xlie = ig_cfg2.xlie; + val->ig2_xhie = ig_cfg2.xhie; + val->ig2_ylie = ig_cfg2.ylie; + val->ig2_yhie = ig_cfg2.yhie; + val->ig2_zlie = ig_cfg2.zlie; + val->ig2_zhie = ig_cfg2.zhie; + + return ret; +} + +/** + * @brief Accelerometer interrupt on threshold source.[get] + * + * @param dev I2C device to use + * @param val Accelerometer’s X low. event.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_src_get(i2c_dev_t *dev, lis2hh12_xl_trshld_src_t *val) +{ + lis2hh12_ig_src1_t ig_src1; + lis2hh12_ig_src2_t ig_src2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_SRC1, (uint8_t *)&ig_src1, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_SRC2, (uint8_t *)&ig_src2, 1); + } + + val->ig1_xl = ig_src1.xl; + val->ig1_xh = ig_src1.xh; + val->ig1_yl = ig_src1.yl; + val->ig1_yh = ig_src1.yh; + val->ig1_zl = ig_src1.zl; + val->ig1_zh = ig_src1.zh; + val->ig1_ia = ig_src1.ia; + val->ig2_xl = ig_src2.xl; + val->ig2_xh = ig_src2.xh; + val->ig2_yl = ig_src2.yl; + val->ig2_yh = ig_src2.yh; + val->ig2_zl = ig_src2.zl; + val->ig2_zh = ig_src2.zh; + val->ig2_ia = ig_src2.ia; + + return ret; +} + +/** + * @brief Axis interrupt threshold.[set] + * + * @param dev I2C device to use + * @param buff Buffer that stores data to be write.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_set(i2c_dev_t *dev, uint8_t ig1_x, uint8_t ig1_y, uint8_t ig1_z, uint8_t ig2_xyz) +{ + esp_err_t ret; + + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_THS_X1, &ig1_x, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_THS_Y1, &ig1_y, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_THS_Z1, &ig1_z, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_THS2, &ig2_xyz, 1); + } + + return ret; +} + +/** + * @brief Axis interrupt threshold.[get] + * + * @param dev I2C device to use + * @param buff Buffer that stores data read.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_get(i2c_dev_t *dev, uint8_t *ig1_x, uint8_t *ig1_y, uint8_t *ig1_z, uint8_t *ig2_xyz) +{ + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_THS_X1, ig1_x, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_THS_Y1, ig1_y, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_THS_Z1, ig1_z, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_THS2, ig2_xyz, 1); + } + + return ret; +} + +/** + * @brief Enter/exit interrupt duration value.[set] + * + * @param dev I2C device to use + * @param val Change the values of dur1 in reg IG_DUR1. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_min_sample_set(i2c_dev_t *dev, uint8_t ig1_sam, uint8_t ig2_sam) +{ + lis2hh12_ig_dur1_t ig_dur1; + lis2hh12_ig_dur2_t ig_dur2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_DUR1, (uint8_t *)&ig_dur1, 1); + + if (ret == ESP_OK) + { + if (ig1_sam == 0x00U) + { + ig_dur1.wait1 = PROPERTY_DISABLE; + } + + else + { + ig_dur1.wait1 = PROPERTY_ENABLE; + } + + ig_dur1.dur1 = ig1_sam; + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_DUR1, (uint8_t *)&ig_dur1, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_DUR2, (uint8_t *)&ig_dur2, 1); + } + + if (ret == ESP_OK) + { + if (ig2_sam == 0x00U) + { + ig_dur2.wait2 = PROPERTY_DISABLE; + } + + else + { + ig_dur2.wait2 = PROPERTY_ENABLE; + } + + ig_dur2.dur2 = ig2_sam; + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_DUR2, (uint8_t *)&ig_dur2, 1); + } + + return ret; +} + +/** + * @brief Enter/exit interrupt duration value.[get] + * + * @param dev I2C device to use + * @param val Get the values of dur1 in reg IG_DUR1.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_trshld_min_sample_get(i2c_dev_t *dev, uint8_t *ig1_sam, uint8_t *ig2_sam) +{ + lis2hh12_ig_dur1_t ig_dur1; + lis2hh12_ig_dur2_t ig_dur2; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_DUR1, (uint8_t *)&ig_dur1, 1); + + if (ret == ESP_OK) + { + *ig1_sam = (uint8_t)ig_dur1.dur1; + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_DUR2, (uint8_t *)&ig_dur2, 1); + } + + if (ret == ESP_OK) + { + *ig2_sam = (uint8_t)ig_dur2.dur2; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Activity/Inactivity_detection + * @brief This section groups all the functions concerning + * activity/inactivity detection. + * @{ + * + */ + +/** + * @brief Inactivity threshold.[set] + * + * @param dev I2C device to use + * @param val Change the values of ths in reg ACT_THS. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_act_threshold_set(i2c_dev_t *dev, uint8_t val) +{ + lis2hh12_act_ths_t act_ths; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_ACT_THS, (uint8_t *)&act_ths, 1); + + if (ret == ESP_OK) + { + act_ths.ths = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_ACT_THS, (uint8_t *)&act_ths, 1); + } + + return ret; +} + +/** + * @brief Inactivity threshold.[get] + * + * @param dev I2C device to use + * @param val Get the values of ths in reg ACT_THS.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_act_threshold_get(i2c_dev_t *dev, uint8_t *val) +{ + lis2hh12_act_ths_t act_ths; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_ACT_THS, (uint8_t *)&act_ths, 1); + + if (ret == ESP_OK) + { + *val = (uint8_t)act_ths.ths; + } + + return ret; +} + +/** + * @brief Inactivity duration in number of sample.[set] + * + * @param dev I2C device to use + * @param val Change the values of dur in reg ACT_DUR. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_act_duration_set(i2c_dev_t *dev, uint8_t val) +{ + lis2hh12_act_dur_t act_dur; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_ACT_DUR, (uint8_t *)&act_dur, 1); + + if (ret == ESP_OK) + { + act_dur.dur = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_ACT_DUR, (uint8_t *)&act_dur, 1); + } + + return ret; +} + +/** + * @brief Inactivity duration in number of sample.[get] + * + * @param dev I2C device to use + * @param val Get the values of dur in reg ACT_DUR.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_act_duration_get(i2c_dev_t *dev, uint8_t *val) +{ + lis2hh12_act_dur_t act_dur; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_ACT_DUR, (uint8_t *)&act_dur, 1); + + if (ret == ESP_OK) + { + *val = (uint8_t)act_dur.dur; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Six_position_detection(6D/4D). + * @brief This section groups all the functions concerning six + * position detection (6D). + * @{ + * + */ + +/** + * @brief 6D feature working mode.[set] + * + * @param dev I2C device to use + * @param val Configure 6D feature working mode. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_6d_mode_set(i2c_dev_t *dev, lis2hh12_6d_mode_t val) +{ + lis2hh12_ig_cfg1_t ig_cfg1; + lis2hh12_ig_cfg2_t ig_cfg2; + lis2hh12_ctrl7_t ctrl7; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + + if (ret == ESP_OK) + { + ctrl7._4d_ig = ((uint8_t)val & 0x10U) >> 4; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + if (ret == ESP_OK) + { + ig_cfg2._6d = ((uint8_t)val & 0x02U) >> 1; + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + } + + if (ret == ESP_OK) + { + ig_cfg1._6d = (uint8_t)val & 0x01U; + ret = lis2hh12_write_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + } + + return ret; +} + +/** + * @brief 6D feature working mode.[get] + * + * @param dev I2C device to use + * @param val Get the configuration of 6D feature.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_6d_mode_get(i2c_dev_t *dev, lis2hh12_6d_mode_t *val) +{ + lis2hh12_ig_cfg1_t ig_cfg1; + lis2hh12_ig_cfg2_t ig_cfg2; + lis2hh12_ctrl7_t ctrl7; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL7, (uint8_t *)&ctrl7, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG2, (uint8_t *)&ig_cfg2, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_IG_CFG1, (uint8_t *)&ig_cfg1, 1); + } + + if (ret != ESP_OK) + { + return ret; + } + + switch ((ctrl7._4d_ig << 4) | (ig_cfg2._6d << 1) | ig_cfg1._6d) + { + case LIS2HH12_6D_4D_DISABLE: + *val = LIS2HH12_6D_4D_DISABLE; + break; + + case LIS2HH12_ENABLE_ON_IG1_6D: + *val = LIS2HH12_ENABLE_ON_IG1_6D; + break; + + case LIS2HH12_ENABLE_ON_IG2_6D: + *val = LIS2HH12_ENABLE_ON_IG2_6D; + break; + + case LIS2HH12_ENABLE_ON_IG1_4D: + *val = LIS2HH12_ENABLE_ON_IG1_4D; + break; + + case LIS2HH12_ENABLE_ON_IG2_4D: + *val = LIS2HH12_ENABLE_ON_IG2_4D; + break; + + default: + *val = LIS2HH12_6D_4D_DISABLE; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Fifo + * @brief This section group all the functions concerning + * the fifo usage + * @{ + * + */ + +/** + * @brief FIFO watermark level selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of stop_fth in reg CTRL3. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_fifo_watermark_set(i2c_dev_t *dev, uint8_t val) +{ + lis2hh12_fifo_ctrl_t fifo_ctrl; + lis2hh12_ctrl3_t ctrl3; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_FIFO_CTRL, (uint8_t *)&fifo_ctrl, 1); + } + + if (ret == ESP_OK) + { + if (val == 0x00U) + { + ctrl3.stop_fth = PROPERTY_DISABLE; + } + + else + { + ctrl3.stop_fth = PROPERTY_ENABLE; + } + + fifo_ctrl.fth = val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_write_reg(dev, LIS2HH12_FIFO_CTRL, (uint8_t *)&fifo_ctrl, 1); + } + + return ret; +} + +/** + * @brief FIFO watermark level selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of stop_fth in reg CTRL3.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_fifo_watermark_get(i2c_dev_t *dev, uint8_t *val) +{ + lis2hh12_fifo_ctrl_t fifo_ctrl; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_FIFO_CTRL, (uint8_t *)&fifo_ctrl, 1); + + if (ret != ESP_OK) + { + return ret; + } + + *val = (uint8_t)fifo_ctrl.fth; + + return ret; +} + +/** + * @brief FIFO mode selection.[set] + * + * @param dev I2C device to use + * @param val Change the values of "fifo_en" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_fifo_mode_set(i2c_dev_t *dev, lis2hh12_fifo_md_t val) +{ + lis2hh12_fifo_ctrl_t fifo_ctrl; + lis2hh12_ctrl3_t ctrl3; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + + if (ret == ESP_OK) + { + ctrl3.fifo_en = (((uint8_t)val & 0x10U) >> 4); + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + } + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_FIFO_CTRL, (uint8_t *)&fifo_ctrl, 1); + } + + if (ret == ESP_OK) + { + fifo_ctrl.fmode = ((uint8_t)val & 0x0FU); + ret = lis2hh12_write_reg(dev, LIS2HH12_FIFO_CTRL, (uint8_t *)&fifo_ctrl, 1); + } + + return ret; +} + +/** + * @brief FIFO mode selection.[get] + * + * @param dev I2C device to use + * @param val Get the values of fifo_en in reg CTRL3.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_fifo_mode_get(i2c_dev_t *dev, lis2hh12_fifo_md_t *val) +{ + lis2hh12_fifo_ctrl_t fifo_ctrl; + lis2hh12_ctrl3_t ctrl3; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL3, (uint8_t *)&ctrl3, 1); + + if (ret == ESP_OK) + { + ret = lis2hh12_read_reg(dev, LIS2HH12_FIFO_CTRL, (uint8_t *)&fifo_ctrl, 1); + } + + if (ret != ESP_OK) + { + return ret; + } + + switch ((ctrl3.fifo_en << 4) | fifo_ctrl.fmode) + { + case LIS2HH12_FIFO_OFF: + *val = LIS2HH12_FIFO_OFF; + break; + + case LIS2HH12_BYPASS_MODE: + *val = LIS2HH12_BYPASS_MODE; + break; + + case LIS2HH12_FIFO_MODE: + *val = LIS2HH12_FIFO_MODE; + break; + + case LIS2HH12_STREAM_MODE: + *val = LIS2HH12_STREAM_MODE; + break; + + case LIS2HH12_STREAM_TO_FIFO_MODE: + *val = LIS2HH12_STREAM_TO_FIFO_MODE; + break; + + case LIS2HH12_BYPASS_TO_STREAM_MODE: + *val = LIS2HH12_BYPASS_TO_STREAM_MODE; + break; + + case LIS2HH12_BYPASS_TO_FIFO_MODE: + *val = LIS2HH12_BYPASS_TO_FIFO_MODE; + break; + + default: + *val = LIS2HH12_FIFO_OFF; + break; + } + + return ret; +} + +/** + * @brief FIFOstatus.[get] + * + * @param dev I2C device to use + * @param val FIFOfullflag.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_fifo_status_get(i2c_dev_t *dev, lis2hh12_fifo_stat_t *val) +{ + lis2hh12_fifo_src_t fifo_src; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_FIFO_SRC, (uint8_t *)&fifo_src, 1); + + if (ret != ESP_OK) + { + return ret; + } + + val->fss = fifo_src.fss; + val->empty = fifo_src.empty; + val->ovr = fifo_src.ovr; + val->fth = fifo_src.fth; + + return ret; +} + +/** + * @} + * + */ + +/** + * @defgroup LIS2HH12_Self_test + * @brief This section groups all the functions that manage + * self test configuration + * @{ + * + */ + +/** + * @brief Enable/disable self-test mode for accelerometer.[set] + * + * @param dev I2C device to use + * @param val Change the values of "st" in reg LIS2HH12. + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_self_test_set(i2c_dev_t *dev, lis2hh12_xl_st_t val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret == ESP_OK) + { + ctrl5.st = (uint8_t)val; + ret = lis2hh12_write_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + } + + return ret; +} + +/** + * @brief Enable/disable self-test mode for accelerometer.[get] + * + * @param dev I2C device to use + * @param val Get the values of st in reg CTRL5.(ptr) + * @retval Interface status. + * + */ +esp_err_t lis2hh12_xl_self_test_get(i2c_dev_t *dev, lis2hh12_xl_st_t *val) +{ + lis2hh12_ctrl5_t ctrl5; + esp_err_t ret; + + ret = lis2hh12_read_reg(dev, LIS2HH12_CTRL5, (uint8_t *)&ctrl5, 1); + + if (ret != ESP_OK) + { + return ret; + } + + switch (ctrl5.st) + { + case LIS2HH12_ST_DISABLE: + *val = LIS2HH12_ST_DISABLE; + break; + + case LIS2HH12_ST_POSITIVE: + *val = LIS2HH12_ST_POSITIVE; + break; + + case LIS2HH12_ST_NEGATIVE: + *val = LIS2HH12_ST_NEGATIVE; + break; + + default: + *val = LIS2HH12_ST_DISABLE; + break; + } + + return ret; +} + +/** + * @} + * + */ + +/** + * @} + * + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/components/lis2hh12/lis2hh12.h b/components/lis2hh12/lis2hh12.h new file mode 100644 index 00000000..b328e8fd --- /dev/null +++ b/components/lis2hh12/lis2hh12.h @@ -0,0 +1,856 @@ +/** + ****************************************************************************** + * @file lis2hh12.h + * @author Sensors Software Solution Team + * @brief This file contains all the functions prototypes for the + * lis2hh12.c driver. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2021 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef LIS2HH12_H +#define LIS2HH12_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +/** @addtogroup LIS2HH12 + * @{ + * + */ + +/** @defgroup Endianness definitions + * @{ + * + */ + +#ifndef DRV_BYTE_ORDER +#ifndef __BYTE_ORDER__ + +#define DRV_LITTLE_ENDIAN 1234 +#define DRV_BIG_ENDIAN 4321 + +/** if _BYTE_ORDER is not defined, choose the endianness of your architecture + * by uncommenting the define which fits your platform endianness + */ +// #define DRV_BYTE_ORDER DRV_BIG_ENDIAN +#define DRV_BYTE_ORDER DRV_LITTLE_ENDIAN + +#else /* defined __BYTE_ORDER__ */ + +#define DRV_LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +#define DRV_BIG_ENDIAN __ORDER_BIG_ENDIAN__ +#define DRV_BYTE_ORDER __BYTE_ORDER__ + +#endif /* __BYTE_ORDER__*/ +#endif /* DRV_BYTE_ORDER */ + +/** + * @} + * + */ + +/** @defgroup STMicroelectronics sensors common types + * @{ + * + */ + +#ifndef MEMS_SHARED_TYPES +#define MEMS_SHARED_TYPES + +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + 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; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bit7 : 1; + uint8_t bit6 : 1; + uint8_t bit5 : 1; + uint8_t bit4 : 1; + uint8_t bit3 : 1; + uint8_t bit2 : 1; + uint8_t bit1 : 1; + uint8_t bit0 : 1; +#endif /* DRV_BYTE_ORDER */ +} bitwise_t; + +#define PROPERTY_DISABLE (0U) +#define PROPERTY_ENABLE (1U) + +/** @addtogroup 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. + * @{ + * + */ + +/** + * @} + * + */ + +#endif /* MEMS_SHARED_TYPES */ + +/** + * @} + * + */ + +/** @defgroup LIS2HH12_Infos + * @{ + * + */ + +/** I2C Device Address 7 bit format if SA0=0 -> 0x1E if SA0=1 -> 0x1D **/ +#define LIS2HH12_ADDR_SA0_L 0x1EU +#define LIS2HH12_ADDR_SA0_H 0x1DU +/** Device Identification (Who am I) **/ +#define LIS2HH12_ID 0x41U + +/** + * @} + * + */ + +#define LIS2HH12_TEMP_L 0x0BU +#define LIS2HH12_TEMP_H 0x0CU +#define LIS2HH12_WHO_AM_I 0x0FU +#define LIS2HH12_ACT_THS 0x1EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t ths : 7; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t ths : 7; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_act_ths_t; + +#define LIS2HH12_ACT_DUR 0x1FU +typedef struct +{ + uint8_t dur : 8; +} lis2hh12_act_dur_t; + +#define LIS2HH12_CTRL1 0x20U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xen : 1; + uint8_t yen : 1; + uint8_t zen : 1; + uint8_t bdu : 1; + uint8_t odr : 3; + uint8_t hr : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t hr : 1; + uint8_t odr : 3; + uint8_t bdu : 1; + uint8_t zen : 1; + uint8_t yen : 1; + uint8_t xen : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ctrl1_t; + +#define LIS2HH12_CTRL2 0x21U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t hpis : 2; + uint8_t fds : 1; + uint8_t hpm : 2; + uint8_t dfc : 2; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t dfc : 2; + uint8_t hpm : 2; + uint8_t fds : 1; + uint8_t hpis : 2; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ctrl2_t; + +#define LIS2HH12_CTRL3 0x22U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int1_drdy : 1; + uint8_t int1_fth : 1; + uint8_t int1_ovr : 1; + uint8_t int1_ig1 : 1; + uint8_t int1_ig2 : 1; + uint8_t int1_inact : 1; + uint8_t stop_fth : 1; + uint8_t fifo_en : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t fifo_en : 1; + uint8_t stop_fth : 1; + uint8_t int1_inact : 1; + uint8_t int1_ig2 : 1; + uint8_t int1_ig1 : 1; + uint8_t int1_ovr : 1; + uint8_t int1_fth : 1; + uint8_t int1_drdy : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ctrl3_t; + +#define LIS2HH12_CTRL4 0x23U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t sim : 1; + uint8_t i2c_disable : 1; + uint8_t if_add_inc : 1; + uint8_t bw_scale_odr : 1; + uint8_t fs : 2; + uint8_t bw : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t bw : 2; + uint8_t fs : 2; + uint8_t bw_scale_odr : 1; + uint8_t if_add_inc : 1; + uint8_t i2c_disable : 1; + uint8_t sim : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ctrl4_t; + +#define LIS2HH12_CTRL5 0x24U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t pp_od : 1; + uint8_t h_lactive : 1; + uint8_t st : 2; + uint8_t dec : 2; + uint8_t soft_reset : 1; + uint8_t debug : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t debug : 1; + uint8_t soft_reset : 1; + uint8_t dec : 2; + uint8_t st : 2; + uint8_t h_lactive : 1; + uint8_t pp_od : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ctrl5_t; + +#define LIS2HH12_CTRL6 0x25U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t int2_drdy : 1; + uint8_t int2_fth : 1; + uint8_t int2_empty : 1; + uint8_t int2_ig1 : 1; + uint8_t int2_ig2 : 1; + uint8_t int2_boot : 1; + uint8_t not_used_01 : 1; + uint8_t boot : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t boot : 1; + uint8_t not_used_01 : 1; + uint8_t int2_boot : 1; + uint8_t int2_ig2 : 1; + uint8_t int2_ig1 : 1; + uint8_t int2_empty : 1; + uint8_t int2_fth : 1; + uint8_t int2_drdy : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ctrl6_t; + +#define LIS2HH12_CTRL7 0x26U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t _4d_ig : 2; + uint8_t lir : 2; + uint8_t dcrm : 2; + uint8_t not_used_01 : 2; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 2; + uint8_t dcrm : 2; + uint8_t lir : 2; + uint8_t _4d_ig : 2; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ctrl7_t; + +#define LIS2HH12_STATUS 0x27U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xda : 1; + uint8_t yda : 1; + uint8_t zda : 1; + uint8_t zyxda : 1; + uint8_t _xor : 1; + uint8_t yor : 1; + uint8_t zor : 1; + uint8_t zyxor : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t zyxor : 1; + uint8_t zor : 1; + uint8_t yor : 1; + uint8_t _xor : 1; + uint8_t zyxda : 1; + uint8_t zda : 1; + uint8_t yda : 1; + uint8_t xda : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_status_t; + +#define LIS2HH12_OUT_X_L 0x28U +#define LIS2HH12_OUT_X_H 0x29U +#define LIS2HH12_OUT_Y_L 0x2AU +#define LIS2HH12_OUT_Y_H 0x2BU +#define LIS2HH12_OUT_Z_L 0x2CU +#define LIS2HH12_OUT_Z_H 0x2DU +#define LIS2HH12_FIFO_CTRL 0x2EU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fth : 5; + uint8_t fmode : 3; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t fmode : 3; + uint8_t fth : 5; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_fifo_ctrl_t; + +#define LIS2HH12_FIFO_SRC 0x2FU +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t fss : 5; + uint8_t empty : 1; + uint8_t ovr : 1; + uint8_t fth : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t fth : 1; + uint8_t ovr : 1; + uint8_t empty : 1; + uint8_t fss : 5; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_fifo_src_t; + +#define LIS2HH12_IG_CFG1 0x30U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xlie : 1; + uint8_t xhie : 1; + uint8_t ylie : 1; + uint8_t yhie : 1; + uint8_t zlie : 1; + uint8_t zhie : 1; + uint8_t _6d : 1; + uint8_t aoi : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t aoi : 1; + uint8_t _6d : 1; + uint8_t zhie : 1; + uint8_t zlie : 1; + uint8_t yhie : 1; + uint8_t ylie : 1; + uint8_t xhie : 1; + uint8_t xlie : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ig_cfg1_t; + +#define LIS2HH12_IG_SRC1 0x31U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xl : 1; + uint8_t xh : 1; + uint8_t yl : 1; + uint8_t yh : 1; + uint8_t zl : 1; + uint8_t zh : 1; + uint8_t ia : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t ia : 1; + uint8_t zh : 1; + uint8_t zl : 1; + uint8_t yh : 1; + uint8_t yl : 1; + uint8_t xh : 1; + uint8_t xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ig_src1_t; + +#define LIS2HH12_IG_THS_X1 0x32U +#define LIS2HH12_IG_THS_Y1 0x33U +#define LIS2HH12_IG_THS_Z1 0x34U +#define LIS2HH12_IG_DUR1 0x35U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t dur1 : 7; + uint8_t wait1 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t wait1 : 1; + uint8_t dur1 : 7; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ig_dur1_t; + +#define LIS2HH12_IG_CFG2 0x36U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xlie : 1; + uint8_t xhie : 1; + uint8_t ylie : 1; + uint8_t yhie : 1; + uint8_t zlie : 1; + uint8_t zhie : 1; + uint8_t _6d : 1; + uint8_t aoi : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t aoi : 1; + uint8_t _6d : 1; + uint8_t zhie : 1; + uint8_t zlie : 1; + uint8_t yhie : 1; + uint8_t ylie : 1; + uint8_t xhie : 1; + uint8_t xlie : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ig_cfg2_t; + +#define LIS2HH12_IG_SRC2 0x37U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t xl : 1; + uint8_t xh : 1; + uint8_t yl : 1; + uint8_t yh : 1; + uint8_t zl : 1; + uint8_t zh : 1; + uint8_t ia : 1; + uint8_t not_used_01 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t not_used_01 : 1; + uint8_t ia : 1; + uint8_t zh : 1; + uint8_t zl : 1; + uint8_t yh : 1; + uint8_t yl : 1; + uint8_t xh : 1; + uint8_t xl : 1; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ig_src2_t; + +#define LIS2HH12_IG_THS2 0x38U +#define LIS2HH12_IG_DUR2 0x39U +typedef struct +{ +#if DRV_BYTE_ORDER == DRV_LITTLE_ENDIAN + uint8_t dur2 : 7; + uint8_t wait2 : 1; +#elif DRV_BYTE_ORDER == DRV_BIG_ENDIAN + uint8_t wait2 : 1; + uint8_t dur2 : 7; +#endif /* DRV_BYTE_ORDER */ +} lis2hh12_ig_dur2_t; + +#define LIS2HH12_XL_REFERENCE 0x3AU +#define LIS2HH12_XH_REFERENCE 0x3BU +#define LIS2HH12_YL_REFERENCE 0x3CU +#define LIS2HH12_YH_REFERENCE 0x3DU +#define LIS2HH12_ZL_REFERENCE 0x3EU +#define LIS2HH12_ZH_REFERENCE 0x3FU + +/** + * @defgroup LIS2HH12_Register_Union + * @brief This union group all the registers having a bit-field + * description. + * This union is useful but it's not needed by the driver. + * + * REMOVING this union you are compliant with: + * MISRA-C 2012 [Rule 19.2] -> " Union are not allowed " + * + * @{ + * + */ +typedef union +{ + lis2hh12_act_ths_t act_ths; + lis2hh12_act_dur_t act_dur; + lis2hh12_ctrl1_t ctrl1; + lis2hh12_ctrl2_t ctrl2; + lis2hh12_ctrl3_t ctrl3; + lis2hh12_ctrl4_t ctrl4; + lis2hh12_ctrl5_t ctrl5; + lis2hh12_ctrl6_t ctrl6; + lis2hh12_ctrl7_t ctrl7; + lis2hh12_status_t status; + lis2hh12_fifo_ctrl_t fifo_ctrl; + lis2hh12_fifo_src_t fifo_src; + lis2hh12_ig_cfg1_t ig_cfg1; + lis2hh12_ig_src1_t ig_src1; + lis2hh12_ig_dur1_t ig_dur1; + lis2hh12_ig_cfg2_t ig_cfg2; + lis2hh12_ig_src2_t ig_src2; + lis2hh12_ig_dur2_t ig_dur2; + bitwise_t bitwise; + uint8_t byte; +} lis2hh12_reg_t; + +/* + * These are the basic platform dependent I/O routines to read + * and write device registers connected on a standard bus. + * The driver keeps offering a default implementation based on function + * pointers to read/write routines for backward compatibility. + * The __weak directive allows the final application to overwrite + * them with a custom implementation. + */ + +esp_err_t lis2hh12_read_reg(i2c_dev_t *dev, uint8_t reg, uint8_t *data, uint16_t len); +esp_err_t lis2hh12_write_reg(i2c_dev_t *dev, uint8_t reg, uint8_t *data, uint16_t len); + +float_t lis2hh12_from_fs2g_to_mg(int16_t lsb); +float_t lis2hh12_from_fs4g_to_mg(int16_t lsb); +float_t lis2hh12_from_fs8g_to_mg(int16_t lsb); + +float_t lis2hh12_from_lsb_to_celsius(int16_t lsb); + +typedef struct +{ + uint8_t xen : 1; + uint8_t yen : 1; + uint8_t zen : 1; +} lis2hh12_xl_axis_t; +esp_err_t lis2hh12_xl_axis_set(i2c_dev_t *dev, lis2hh12_xl_axis_t val); +esp_err_t lis2hh12_xl_axis_get(i2c_dev_t *dev, lis2hh12_xl_axis_t *val); + +esp_err_t lis2hh12_block_data_update_set(i2c_dev_t *dev, uint8_t val); +esp_err_t lis2hh12_block_data_update_get(i2c_dev_t *dev, uint8_t *val); + +typedef enum { + LIS2HH12_XL_ODR_OFF = 0x00, + LIS2HH12_XL_ODR_10Hz = 0x01, + LIS2HH12_XL_ODR_50Hz = 0x02, + LIS2HH12_XL_ODR_100Hz = 0x03, + LIS2HH12_XL_ODR_200Hz = 0x04, + LIS2HH12_XL_ODR_400Hz = 0x05, + LIS2HH12_XL_ODR_800Hz = 0x06, +} lis2hh12_xl_data_rate_t; +esp_err_t lis2hh12_xl_data_rate_set(i2c_dev_t *dev, lis2hh12_xl_data_rate_t val); +esp_err_t lis2hh12_xl_data_rate_get(i2c_dev_t *dev, lis2hh12_xl_data_rate_t *val); + +typedef enum { + LIS2HH12_2g = 0x00, + LIS2HH12_16g = 0x01, + LIS2HH12_4g = 0x02, + LIS2HH12_8g = 0x03, +} lis2hh12_xl_fs_t; +esp_err_t lis2hh12_xl_full_scale_set(i2c_dev_t *dev, lis2hh12_xl_fs_t val); +esp_err_t lis2hh12_xl_full_scale_get(i2c_dev_t *dev, lis2hh12_xl_fs_t *val); + +typedef enum { + LIS2HH12_NO_DECIMATION = 0x00, + LIS2HH12_EVERY_2_SAMPLES = 0x01, + LIS2HH12_EVERY_4_SAMPLES = 0x02, + LIS2HH12_EVERY_8_SAMPLES = 0x03, +} lis2hh12_dec_t; +esp_err_t lis2hh12_xl_decimation_set(i2c_dev_t *dev, lis2hh12_dec_t val); +esp_err_t lis2hh12_xl_decimation_get(i2c_dev_t *dev, lis2hh12_dec_t *val); + +esp_err_t lis2hh12_xl_flag_data_ready_get(i2c_dev_t *dev, uint8_t *val); + +esp_err_t lis2hh12_temperature_raw_get(i2c_dev_t *dev, int16_t *val); + +esp_err_t lis2hh12_acceleration_raw_get(i2c_dev_t *dev, int16_t *val); + +esp_err_t lis2hh12_init_desc(i2c_dev_t *dev, i2c_port_t port, gpio_num_t sda_gpio, gpio_num_t scl_gpio, bool pin_sa0); + +esp_err_t lis2hh12_free_desc(i2c_dev_t *dev); + +esp_err_t lis2hh12_dev_id_get(i2c_dev_t *dev, uint8_t *buff); + +esp_err_t lis2hh12_dev_reset_set(i2c_dev_t *dev, uint8_t val); +esp_err_t lis2hh12_dev_reset_get(i2c_dev_t *dev, uint8_t *val); + +esp_err_t lis2hh12_dev_boot_set(i2c_dev_t *dev, uint8_t val); +esp_err_t lis2hh12_dev_boot_get(i2c_dev_t *dev, uint8_t *val); + +typedef struct +{ + uint8_t xda : 1; + uint8_t yda : 1; + uint8_t zda : 1; + uint8_t zyxda : 1; + uint8_t _xor : 1; + uint8_t yor : 1; + uint8_t zor : 1; + uint8_t zyxor : 1; +} lis2hh12_status_reg_t; +esp_err_t lis2hh12_dev_status_get(i2c_dev_t *dev, lis2hh12_status_reg_t *val); + +typedef enum { + LIS2HH12_HP_DISABLE = 0x00, + LIS2HH12_HP_ON_INT_GEN_1 = 0x02, + LIS2HH12_HP_ON_INT_GEN_2 = 0x01, + LIS2HH12_HP_ON_BOTH_GEN = 0x03, +} lis2hh12_xl_hp_path_t; +esp_err_t lis2hh12_xl_filter_int_path_set(i2c_dev_t *dev, lis2hh12_xl_hp_path_t val); +esp_err_t lis2hh12_xl_filter_int_path_get(i2c_dev_t *dev, lis2hh12_xl_hp_path_t *val); + +typedef enum { + LIS2HH12_BYPASSED = 0x00, + LIS2HH12_FILT_HP = 0x02, + LIS2HH12_FILT_LP = 0x01, +} lis2hh12_xl_out_path_t; +esp_err_t lis2hh12_xl_filter_out_path_set(i2c_dev_t *dev, lis2hh12_xl_out_path_t val); +esp_err_t lis2hh12_xl_filter_out_path_get(i2c_dev_t *dev, lis2hh12_xl_out_path_t *val); + +typedef enum { + LIS2HH12_HP_ODR_DIV_50 = 0x00, + LIS2HH12_HP_ODR_DIV_100 = 0x10, + LIS2HH12_HP_ODR_DIV_9 = 0x20, + LIS2HH12_HP_ODR_DIV_400 = 0x30, + LIS2HH12_HP_ODR_DIV_50_REF_MD = 0x01, + LIS2HH12_HP_ODR_DIV_100_REF_MD = 0x11, + LIS2HH12_HP_ODR_DIV_9_REF_MD = 0x21, + LIS2HH12_HP_ODR_DIV_400_REF_MD = 0x31, +} lis2hh12_xl_hp_bw_t; +esp_err_t lis2hh12_xl_filter_hp_bandwidth_set(i2c_dev_t *dev, lis2hh12_xl_hp_bw_t val); +esp_err_t lis2hh12_xl_filter_hp_bandwidth_get(i2c_dev_t *dev, lis2hh12_xl_hp_bw_t *val); + +typedef enum { + LIS2HH12_LP_ODR_DIV_50 = 0, + LIS2HH12_LP_ODR_DIV_100 = 1, + LIS2HH12_LP_ODR_DIV_9 = 2, + LIS2HH12_LP_ODR_DIV_400 = 3, +} lis2hh12_xl_lp_bw_t; +esp_err_t lis2hh12_xl_filter_low_bandwidth_set(i2c_dev_t *dev, lis2hh12_xl_lp_bw_t val); +esp_err_t lis2hh12_xl_filter_low_bandwidth_get(i2c_dev_t *dev, lis2hh12_xl_lp_bw_t *val); + +typedef enum { + LIS2HH12_AUTO = 0x00, + LIS2HH12_408Hz = 0x10, + LIS2HH12_211Hz = 0x11, + LIS2HH12_105Hz = 0x12, + LIS2HH12_50Hz = 0x13, +} lis2hh12_xl_filt_aa_bw_t; +esp_err_t lis2hh12_xl_filter_aalias_bandwidth_set(i2c_dev_t *dev, lis2hh12_xl_filt_aa_bw_t val); +esp_err_t lis2hh12_xl_filter_aalias_bandwidth_get(i2c_dev_t *dev, lis2hh12_xl_filt_aa_bw_t *val); + +esp_err_t lis2hh12_xl_filter_reference_set(i2c_dev_t *dev, int16_t *val); +esp_err_t lis2hh12_xl_filter_reference_get(i2c_dev_t *dev, int16_t *val); + +typedef enum { + LIS2HH12_SPI_4_WIRE = 0x00, + LIS2HH12_SPI_3_WIRE = 0x01, +} lis2hh12_sim_t; +esp_err_t lis2hh12_spi_mode_set(i2c_dev_t *dev, lis2hh12_sim_t val); +esp_err_t lis2hh12_spi_mode_get(i2c_dev_t *dev, lis2hh12_sim_t *val); + +typedef enum { + LIS2HH12_I2C_ENABLE = 0x00, + LIS2HH12_I2C_DISABLE = 0x01, +} lis2hh12_i2c_dis_t; +esp_err_t lis2hh12_i2c_interface_set(i2c_dev_t *dev, lis2hh12_i2c_dis_t val); +esp_err_t lis2hh12_i2c_interface_get(i2c_dev_t *dev, lis2hh12_i2c_dis_t *val); + +typedef enum { + LIS2HH12_DISABLE = 0x00, + LIS2HH12_ENABLE = 0x01, +} lis2hh12_auto_inc_t; +esp_err_t lis2hh12_auto_increment_set(i2c_dev_t *dev, lis2hh12_auto_inc_t val); +esp_err_t lis2hh12_auto_increment_get(i2c_dev_t *dev, lis2hh12_auto_inc_t *val); + +typedef struct +{ + uint8_t int1_drdy : 1; + uint8_t int1_fth : 1; + uint8_t int1_ovr : 1; + uint8_t int1_ig1 : 1; + uint8_t int1_ig2 : 1; + uint8_t int1_inact : 1; +} lis2hh12_pin_int1_route_t; +esp_err_t lis2hh12_pin_int1_route_set(i2c_dev_t *dev, lis2hh12_pin_int1_route_t val); +esp_err_t lis2hh12_pin_int1_route_get(i2c_dev_t *dev, lis2hh12_pin_int1_route_t *val); + +typedef enum { + LIS2HH12_PUSH_PULL = 0x00, + LIS2HH12_OPEN_DRAIN = 0x01, +} lis2hh12_pp_od_t; +esp_err_t lis2hh12_pin_mode_set(i2c_dev_t *dev, lis2hh12_pp_od_t val); +esp_err_t lis2hh12_pin_mode_get(i2c_dev_t *dev, lis2hh12_pp_od_t *val); + +typedef enum { + LIS2HH12_ACTIVE_HIGH = 0x00, + LIS2HH12_ACTIVE_LOW = 0x01, +} lis2hh12_pin_pol_t; +esp_err_t lis2hh12_pin_polarity_set(i2c_dev_t *dev, lis2hh12_pin_pol_t val); +esp_err_t lis2hh12_pin_polarity_get(i2c_dev_t *dev, lis2hh12_pin_pol_t *val); + +typedef struct +{ + uint8_t int2_drdy : 1; + uint8_t int2_fth : 1; + uint8_t int2_empty : 1; + uint8_t int2_ig1 : 1; + uint8_t int2_ig2 : 1; + uint8_t int2_boot : 1; +} lis2hh12_pin_int2_route_t; +esp_err_t lis2hh12_pin_int2_route_set(i2c_dev_t *dev, lis2hh12_pin_int2_route_t val); +esp_err_t lis2hh12_pin_int2_route_get(i2c_dev_t *dev, lis2hh12_pin_int2_route_t *val); + +typedef enum { + LIS2HH12_INT_PULSED = 0x00, + LIS2HH12_INT_LATCHED = 0x01, +} lis2hh12_lir_t; +esp_err_t lis2hh12_pin_notification_set(i2c_dev_t *dev, lis2hh12_lir_t val); +esp_err_t lis2hh12_pin_notification_get(i2c_dev_t *dev, lis2hh12_lir_t *val); +typedef enum { + LIS2HH12_IG1_OR_IG2_OR = 0x00, + LIS2HH12_IG1_AND_IG2_OR = 0x01, + LIS2HH12_IG1_OR_IG2_AND = 0x10, + LIS2HH12_IG1_AND_IG2_AND = 0x11, +} lis2hh12_pin_logic_t; +esp_err_t lis2hh12_pin_logic_set(i2c_dev_t *dev, lis2hh12_pin_logic_t val); +esp_err_t lis2hh12_pin_logic_get(i2c_dev_t *dev, lis2hh12_pin_logic_t *val); + +typedef enum { + LIS2HH12_RESET_MODE = 0x00, + LIS2HH12_DECREMENT_MODE = 0x01, +} lis2hh12_dcrm_t; +esp_err_t lis2hh12_xl_trshld_mode_set(i2c_dev_t *dev, lis2hh12_dcrm_t val); +esp_err_t lis2hh12_xl_trshld_mode_get(i2c_dev_t *dev, lis2hh12_dcrm_t *val); + +typedef struct +{ + uint16_t ig1_xlie : 1; + uint16_t ig1_xhie : 1; + uint16_t ig1_ylie : 1; + uint16_t ig1_yhie : 1; + uint16_t ig1_zlie : 1; + uint16_t ig1_zhie : 1; + uint16_t ig2_xlie : 1; + uint16_t ig2_xhie : 1; + uint16_t ig2_ylie : 1; + uint16_t ig2_yhie : 1; + uint16_t ig2_zlie : 1; + uint16_t ig2_zhie : 1; +} lis2hh12_xl_trshld_en_t; +esp_err_t lis2hh12_xl_trshld_axis_set(i2c_dev_t *dev, lis2hh12_xl_trshld_en_t val); +esp_err_t lis2hh12_xl_trshld_axis_get(i2c_dev_t *dev, lis2hh12_xl_trshld_en_t *val); + +typedef struct +{ + uint16_t ig1_xl : 1; + uint16_t ig1_xh : 1; + uint16_t ig1_yl : 1; + uint16_t ig1_yh : 1; + uint16_t ig1_zl : 1; + uint16_t ig1_zh : 1; + uint16_t ig1_ia : 1; + uint16_t ig2_xl : 1; + uint16_t ig2_xh : 1; + uint16_t ig2_yl : 1; + uint16_t ig2_yh : 1; + uint16_t ig2_zl : 1; + uint16_t ig2_zh : 1; + uint16_t ig2_ia : 1; +} lis2hh12_xl_trshld_src_t; +esp_err_t lis2hh12_xl_trshld_src_get(i2c_dev_t *dev, lis2hh12_xl_trshld_src_t *val); + +esp_err_t lis2hh12_xl_trshld_set(i2c_dev_t *dev, uint8_t ig1_x, uint8_t ig1_y, uint8_t ig1_z, uint8_t ig2_xyz); +esp_err_t lis2hh12_xl_trshld_get(i2c_dev_t *dev, uint8_t *ig1_x, uint8_t *ig1_y, uint8_t *ig1_z, uint8_t *ig2_xyz); + +esp_err_t lis2hh12_xl_trshld_min_sample_set(i2c_dev_t *dev, uint8_t ig1_sam, uint8_t ig2_sam); +esp_err_t lis2hh12_xl_trshld_min_sample_get(i2c_dev_t *dev, uint8_t *ig1_sam, uint8_t *ig2_sam); + +esp_err_t lis2hh12_act_threshold_set(i2c_dev_t *dev, uint8_t val); +esp_err_t lis2hh12_act_threshold_get(i2c_dev_t *dev, uint8_t *val); + +esp_err_t lis2hh12_act_duration_set(i2c_dev_t *dev, uint8_t val); +esp_err_t lis2hh12_act_duration_get(i2c_dev_t *dev, uint8_t *val); + +typedef enum { + LIS2HH12_6D_4D_DISABLE = 0x00, + LIS2HH12_ENABLE_ON_IG1_6D = 0x01, + LIS2HH12_ENABLE_ON_IG2_6D = 0x02, + LIS2HH12_ENABLE_ON_IG1_4D = 0x11, + LIS2HH12_ENABLE_ON_IG2_4D = 0x12, +} lis2hh12_6d_mode_t; +esp_err_t lis2hh12_6d_mode_set(i2c_dev_t *dev, lis2hh12_6d_mode_t val); +esp_err_t lis2hh12_6d_mode_get(i2c_dev_t *dev, lis2hh12_6d_mode_t *val); + +esp_err_t lis2hh12_fifo_watermark_set(i2c_dev_t *dev, uint8_t val); +esp_err_t lis2hh12_fifo_watermark_get(i2c_dev_t *dev, uint8_t *val); + +typedef enum { + LIS2HH12_FIFO_OFF = 0x00, + LIS2HH12_BYPASS_MODE = 0x10, + LIS2HH12_FIFO_MODE = 0x11, + LIS2HH12_STREAM_MODE = 0x12, + LIS2HH12_STREAM_TO_FIFO_MODE = 0x13, + LIS2HH12_BYPASS_TO_STREAM_MODE = 0x14, + LIS2HH12_BYPASS_TO_FIFO_MODE = 0x17, +} lis2hh12_fifo_md_t; +esp_err_t lis2hh12_fifo_mode_set(i2c_dev_t *dev, lis2hh12_fifo_md_t val); +esp_err_t lis2hh12_fifo_mode_get(i2c_dev_t *dev, lis2hh12_fifo_md_t *val); + +typedef struct +{ + uint8_t fss : 5; + uint8_t empty : 1; + uint8_t ovr : 1; + uint8_t fth : 1; +} lis2hh12_fifo_stat_t; +esp_err_t lis2hh12_fifo_status_get(i2c_dev_t *dev, lis2hh12_fifo_stat_t *val); + +typedef enum { + LIS2HH12_ST_DISABLE = 0x00, + LIS2HH12_ST_POSITIVE = 0x01, + LIS2HH12_ST_NEGATIVE = 0x02, +} lis2hh12_xl_st_t; +esp_err_t lis2hh12_xl_self_test_set(i2c_dev_t *dev, lis2hh12_xl_st_t val); +esp_err_t lis2hh12_xl_self_test_get(i2c_dev_t *dev, lis2hh12_xl_st_t *val); + +/** + *@} + * + */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIS2HH12_H */ + +/************************ (C) COPYRIGHT STMicroelectronics, Ferdinand Keil *****END OF FILE****/ diff --git a/examples/lis2hh12/default/CMakeLists.txt b/examples/lis2hh12/default/CMakeLists.txt new file mode 100644 index 00000000..a6aea69e --- /dev/null +++ b/examples/lis2hh12/default/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +set(EXTRA_COMPONENT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../../../components) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(example-lis2hh12) diff --git a/examples/lis2hh12/default/Makefile b/examples/lis2hh12/default/Makefile new file mode 100644 index 00000000..22fe17f7 --- /dev/null +++ b/examples/lis2hh12/default/Makefile @@ -0,0 +1,6 @@ +#V := 1 +PROJECT_NAME := example-lis2hh12 + +EXTRA_COMPONENT_DIRS := $(CURDIR)/../../../components + +include $(IDF_PATH)/make/project.mk diff --git a/examples/lis2hh12/default/README.md b/examples/lis2hh12/default/README.md new file mode 100644 index 00000000..88f5b2c2 --- /dev/null +++ b/examples/lis2hh12/default/README.md @@ -0,0 +1,24 @@ +# Example for `lis2hh12` driver + +## What it does + +First, runs the device self test procedure. + +If successful, starts reading the acceleration data in polling mode. + +## Wiring + +Connect `SCL` and `SDA` pins to the following pins with appropriate pull-up +resistors. + +| Name | Description | Defaults | +|------|-------------|----------| +| `CONFIG_EXAMPLE_I2C_MASTER_SCL` | GPIO number for `SCL` | "5" for `esp8266`, "6" for `esp32c3`, "19" for `esp32`, `esp32s2`, and `esp32s3` | +| `CONFIG_EXAMPLE_I2C_MASTER_SDA` | GPIO number for `SDA` | "4" for `esp8266`, "5" for `esp32c3`, "18" for `esp32`, `esp32s2`, and `esp32s3` | +| `CONFIG_EXAMPLE_LIS2HH12_SA0_PIN` | Level of the pin `SA0` on the LIS2HH12 | not selected (LOW) | + +## Based on + +This code is based on the examples `lis2hh12_self_test.c` and +`lis2hh12_data_polling.c` by ST Microelectronics. They can be found here: +https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/lis2hh12_STdC/examples \ No newline at end of file diff --git a/examples/lis2hh12/default/main/CMakeLists.txt b/examples/lis2hh12/default/main/CMakeLists.txt new file mode 100644 index 00000000..cf2c455c --- /dev/null +++ b/examples/lis2hh12/default/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS ".") diff --git a/examples/lis2hh12/default/main/Kconfig.projbuild b/examples/lis2hh12/default/main/Kconfig.projbuild new file mode 100644 index 00000000..1437b772 --- /dev/null +++ b/examples/lis2hh12/default/main/Kconfig.projbuild @@ -0,0 +1,23 @@ +menu "Example configuration" + config EXAMPLE_I2C_MASTER_SCL + int "SCL GPIO Number" + default 5 if IDF_TARGET_ESP8266 + default 6 if IDF_TARGET_ESP32C3 + default 19 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + help + GPIO number for I2C Master clock line. + + config EXAMPLE_I2C_MASTER_SDA + int "SDA GPIO Number" + default 4 if IDF_TARGET_ESP8266 + default 5 if IDF_TARGET_ESP32C3 + default 18 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 + help + GPIO number for I2C Master data line. + + config EXAMPLE_LIS2HH12_SA0_PIN + bool "SA0 pin level" + default n + help + Level of the SA0 pin (true = HIGH). +endmenu diff --git a/examples/lis2hh12/default/main/component.mk b/examples/lis2hh12/default/main/component.mk new file mode 100644 index 00000000..7700ea99 --- /dev/null +++ b/examples/lis2hh12/default/main/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_INCLUDEDIRS = . include/ diff --git a/examples/lis2hh12/default/main/main.c b/examples/lis2hh12/default/main/main.c new file mode 100644 index 00000000..710875ad --- /dev/null +++ b/examples/lis2hh12/default/main/main.c @@ -0,0 +1,266 @@ +/** + * BSD 3-Clause License + * + * Copyright (c) 2019, STMicroelectronics + * Copyright (c) 2024, Ferdinand Keil + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of the copyright holder 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 +#include +#include +#include +#include +#include "esp_log.h" + +#define TAG "example-lis2hh12" + +#ifndef CONFIG_EXAMPLE_LIS2HH12_SA0_PIN +#define CONFIG_EXAMPLE_LIS2HH12_SA0_PIN_LEVEL false +#else +#define CONFIG_EXAMPLE_LIS2HH12_SA0_PIN_LEVEL true +#endif + +#define BOOT_TIME 20 // ms +#define WAIT_TIME 100 // ms + +/* Self test limits. */ +#define MIN_ST_LIMIT_mg 70.0f +#define MAX_ST_LIMIT_mg 1500.0f + +/* Self test results. */ +#define ST_PASS 1U +#define ST_FAIL 0U + +void lis2hh12_test(void *pvParameters) +{ + uint8_t whoamI; + uint8_t rst; + uint8_t drdy; + uint8_t st_result; + uint8_t i; + uint8_t j; + int16_t data_raw[3]; + float val_st_off[3]; + float val_st_on[3]; + float test_val[3]; + float acceleration_mg[3]; + + i2c_dev_t dev; + memset(&dev, 0, sizeof(i2c_dev_t)); + + ESP_ERROR_CHECK(lis2hh12_init_desc(&dev, 0, CONFIG_EXAMPLE_I2C_MASTER_SDA, CONFIG_EXAMPLE_I2C_MASTER_SCL, CONFIG_EXAMPLE_LIS2HH12_SA0_PIN_LEVEL)); + + /* Wait sensor boot time */ + vTaskDelay(pdMS_TO_TICKS(BOOT_TIME)); + + ESP_ERROR_CHECK(lis2hh12_dev_id_get(&dev, &whoamI)); + + if (whoamI != LIS2HH12_ID) + { + ESP_LOGE(TAG, "incorrect device ID (got 0x%02x, expected 0x%02x)", whoamI, LIS2HH12_ID); + while (1) + ; + } + ESP_LOGI(TAG, "found LIS2HH12 device"); + + /* Restore default configuration */ + ESP_ERROR_CHECK(lis2hh12_dev_reset_set(&dev, PROPERTY_ENABLE)); + + do + { + ESP_ERROR_CHECK(lis2hh12_dev_reset_get(&dev, &rst)); + } + while (rst); + + /* Enable Block Data Update */ + ESP_ERROR_CHECK(lis2hh12_block_data_update_set(&dev, PROPERTY_ENABLE)); + + /* + * Accelerometer Self Test + */ + /* Set Output Data Rate */ + ESP_ERROR_CHECK(lis2hh12_xl_data_rate_set(&dev, LIS2HH12_XL_ODR_50Hz)); + /* Set full scale */ + ESP_ERROR_CHECK(lis2hh12_xl_full_scale_set(&dev, LIS2HH12_4g)); + /* Wait stable output */ + vTaskDelay(pdMS_TO_TICKS(WAIT_TIME)); + + /* Check if new value available */ + do + { + ESP_ERROR_CHECK(lis2hh12_xl_flag_data_ready_get(&dev, &drdy)); + } + while (!drdy); + + /* Read dummy data and discard it */ + ESP_ERROR_CHECK(lis2hh12_acceleration_raw_get(&dev, data_raw)); + + /* Read 5 sample and get the average vale for each axis */ + memset(val_st_off, 0x00, 3 * sizeof(float)); + + for (i = 0; i < 5; i++) + { + /* Check if new value available */ + do + { + ESP_ERROR_CHECK(lis2hh12_xl_flag_data_ready_get(&dev, &drdy)); + } + while (!drdy); + + /* Read data and accumulate the mg value */ + ESP_ERROR_CHECK(lis2hh12_acceleration_raw_get(&dev, data_raw)); + + for (j = 0; j < 3; j++) + { + val_st_off[j] += lis2hh12_from_fs4g_to_mg(data_raw[j]); + } + } + + /* Calculate the mg average values */ + for (i = 0; i < 3; i++) + { + val_st_off[i] /= 5.0f; + } + + /* Enable Self Test positive (or negative) */ + ESP_ERROR_CHECK(lis2hh12_xl_self_test_set(&dev, LIS2HH12_ST_NEGATIVE)); + /* Wait stable output */ + vTaskDelay(pdMS_TO_TICKS(WAIT_TIME)); + + /* Check if new value available */ + do + { + ESP_ERROR_CHECK(lis2hh12_xl_flag_data_ready_get(&dev, &drdy)); + } + while (!drdy); + + /* Read dummy data and discard it */ + ESP_ERROR_CHECK(lis2hh12_acceleration_raw_get(&dev, data_raw)); + /* Read 5 sample and get the average vale for each axis */ + memset(val_st_on, 0x00, 3 * sizeof(float)); + + for (i = 0; i < 5; i++) + { + /* Check if new value available */ + do + { + ESP_ERROR_CHECK(lis2hh12_xl_flag_data_ready_get(&dev, &drdy)); + } + while (!drdy); + + /* Read data and accumulate the mg value */ + ESP_ERROR_CHECK(lis2hh12_acceleration_raw_get(&dev, data_raw)); + + for (j = 0; j < 3; j++) + { + val_st_on[j] += lis2hh12_from_fs4g_to_mg(data_raw[j]); + } + } + + /* Calculate the mg average values */ + for (i = 0; i < 3; i++) + { + val_st_on[i] /= 5.0f; + } + + /* Calculate the mg values for self test */ + for (i = 0; i < 3; i++) + { + test_val[i] = fabs((val_st_on[i] - val_st_off[i])); + } + + /* Check self test limit */ + st_result = ST_PASS; + + for (i = 0; i < 3; i++) + { + if ((MIN_ST_LIMIT_mg > test_val[i]) || (test_val[i] > MAX_ST_LIMIT_mg)) + { + st_result = ST_FAIL; + } + } + + /* Disable Self Test */ + ESP_ERROR_CHECK(lis2hh12_xl_self_test_set(&dev, LIS2HH12_ST_DISABLE)); + /* Disable sensor. */ + ESP_ERROR_CHECK(lis2hh12_xl_data_rate_set(&dev, LIS2HH12_XL_ODR_OFF)); + + if (st_result == ST_PASS) + { + ESP_LOGI(TAG, "Self Test - PASS"); + } + else + { + ESP_LOGI(TAG, "Self Test - FAIL"); + } + + /* Enable Block Data Update */ + ESP_ERROR_CHECK(lis2hh12_block_data_update_set(&dev, PROPERTY_ENABLE)); + /* Set full scale */ + ESP_ERROR_CHECK(lis2hh12_xl_full_scale_set(&dev, LIS2HH12_8g)); + /* Configure filtering chain */ + /* Accelerometer data output- filter path / bandwidth */ + ESP_ERROR_CHECK(lis2hh12_xl_filter_aalias_bandwidth_set(&dev, LIS2HH12_AUTO)); + ESP_ERROR_CHECK(lis2hh12_xl_filter_out_path_set(&dev, LIS2HH12_FILT_LP)); + ESP_ERROR_CHECK(lis2hh12_xl_filter_low_bandwidth_set(&dev, LIS2HH12_LP_ODR_DIV_400)); + /* Accelerometer interrupt - filter path / bandwidth */ + ESP_ERROR_CHECK(lis2hh12_xl_filter_int_path_set(&dev, LIS2HH12_HP_DISABLE)); + /* Set Output Data Rate */ + ESP_ERROR_CHECK(lis2hh12_xl_data_rate_set(&dev, LIS2HH12_XL_ODR_100Hz)); + + /* Read samples in polling mode (no int) */ + while (1) + { + uint8_t reg; + /* Read output only if new value is available */ + ESP_ERROR_CHECK(lis2hh12_xl_flag_data_ready_get(&dev, ®)); + + if (reg) + { + /* Read acceleration data */ + memset(data_raw, 0x00, 3 * sizeof(int16_t)); + ESP_ERROR_CHECK(lis2hh12_acceleration_raw_get(&dev, data_raw)); + acceleration_mg[0] = lis2hh12_from_fs8g_to_mg(data_raw[0]); + acceleration_mg[1] = lis2hh12_from_fs8g_to_mg(data_raw[1]); + acceleration_mg[2] = lis2hh12_from_fs8g_to_mg(data_raw[2]); + ESP_LOGI(TAG, "Acceleration [mg]:\t%4.2f\t%4.2f\t%4.2f\r\n", acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]); + } + + vTaskDelay(pdMS_TO_TICKS(WAIT_TIME)); + } + + vTaskDelete(NULL); +} + +void app_main() +{ + ESP_ERROR_CHECK(i2cdev_init()); + + xTaskCreate(lis2hh12_test, "lis2hh12_test", configMINIMAL_STACK_SIZE * 8, NULL, 5, NULL); +}