From 430e10f2824e0acd61f169f4889847a486dc211f Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 8 Dec 2023 16:02:57 +0100 Subject: [PATCH] new driver for the lis2de12 accelerometer (based on the existing lis2dh12 sensor) --- drivers/include/lis2de12.h | 176 +++++++ drivers/lis2de12/Kconfig | 11 + drivers/lis2de12/Makefile | 1 + drivers/lis2de12/Makefile.dep | 1 + drivers/lis2de12/Makefile.include | 2 + drivers/lis2de12/include/lis2de12_constants.h | 38 ++ drivers/lis2de12/include/lis2de12_params.h | 70 +++ drivers/lis2de12/include/lis2de12_registers.h | 476 ++++++++++++++++++ drivers/lis2de12/lis2de12.c | 340 +++++++++++++ drivers/lis2de12/lis2de12_internal.h | 81 +++ tests/drivers/lis2de12/Makefile | 11 + tests/drivers/lis2de12/Makefile.ci | 13 + tests/drivers/lis2de12/README.md | 14 + tests/drivers/lis2de12/app.config.test | 9 + tests/drivers/lis2de12/main.c | 185 +++++++ 15 files changed, 1428 insertions(+) create mode 100644 drivers/include/lis2de12.h create mode 100644 drivers/lis2de12/Kconfig create mode 100644 drivers/lis2de12/Makefile create mode 100644 drivers/lis2de12/Makefile.dep create mode 100644 drivers/lis2de12/Makefile.include create mode 100644 drivers/lis2de12/include/lis2de12_constants.h create mode 100644 drivers/lis2de12/include/lis2de12_params.h create mode 100644 drivers/lis2de12/include/lis2de12_registers.h create mode 100644 drivers/lis2de12/lis2de12.c create mode 100644 drivers/lis2de12/lis2de12_internal.h create mode 100644 tests/drivers/lis2de12/Makefile create mode 100644 tests/drivers/lis2de12/Makefile.ci create mode 100644 tests/drivers/lis2de12/README.md create mode 100644 tests/drivers/lis2de12/app.config.test create mode 100644 tests/drivers/lis2de12/main.c diff --git a/drivers/include/lis2de12.h b/drivers/include/lis2de12.h new file mode 100644 index 000000000000..608219dceaa5 --- /dev/null +++ b/drivers/include/lis2de12.h @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2023 LIG + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup drivers_lis2de12 lis2de12 + * @ingroup drivers_sensors + * @brief driver for the lis2de12 accelerometer + * + * @{ + * + * @file + * + * @author Léo + */ + +#ifndef LIS2DE12_H +#define LIS2DE12_H + +/* Add header includes here */ +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Declare the API of the driver */ + +/** + * @brief Available scale values + */ +typedef enum { + LIS2DE12_SCALE_2G = 0x0, /**< +- 2g */ + LIS2DE12_SCALE_4G = 0x1, /**< +- 4g */ + LIS2DE12_SCALE_8G = 0x2, /**< +- 8g */ + LIS2DE12_SCALE_16G = 0x3, /**< +- 16g */ +} lis2de12_scale_t; + +/** + * @brief Available sampling rates + * + */ +typedef enum { + LIS2DE12_RATE_1HZ = 0x1, /**< sample with 1Hz @ all resolutions */ + LIS2DE12_RATE_10HZ = 0x2, /**< sample with 10Hz @ all resolutions */ + LIS2DE12_RATE_25HZ = 0x3, /**< sample with 25Hz @ all resolutions */ + LIS2DE12_RATE_50HZ = 0x4, /**< sample with 50Hz @ all resolutions */ + LIS2DE12_RATE_100HZ = 0x5, /**< sample with 100Hz @ all resolutions */ + LIS2DE12_RATE_200HZ = 0x6, /**< sample with 200Hz @ all resolutions */ + LIS2DE12_RATE_400HZ = 0x7, /**< sample with 400Hz @ all resolutions */ + LIS2DE12_RATE_1620HZ = 0x8, /**< sample with 1620HZ @ 8-bit */ + LIS2DE12_RATE_VERYHIGH = 0x9, /**< sample with 1344Hz @ High resolution or \ + 5376Hz @ 8-bit */ +} lis2de12_rate_t; + +/** + * @brief Device initialization parameters + */ +typedef struct { + /* add initialization params here */ + i2c_t i2c; /**< I2C bus the device is connected to */ + uint8_t addr; /**< device address on the I2C bus */ +} lis2de12_params_t; + +/** + * @brief LIS2DE12 FIFO data struct + */ +typedef union { + struct { + int16_t x; /**< X data in mili-g */ + int16_t y; /**< Y data in mili-g */ + int16_t z; /**< Z data in mili-g */ + } axis; /**< named axis access */ + int16_t data[3]; /**< x, y, z data in mili-g */ +} lis2de12_fifo_data_t; + +/** + * @brief LIS2DE12 FIFO modes + */ +typedef enum { + LIS2DE12_FIFO_MODE_BYPASS = 0, /**< default mode, FIFO is bypassed */ + LIS2DE12_FIFO_MODE_FIFOMODE, /**< normal FIFO mode, stops if FIFO is full */ + LIS2DE12_FIFO_MODE_STREAM, /**< Stream mode, oldest values get overwritten */ + LIS2DE12_FIFO_MODE_STREAMtoFIFO, /**< Stream mode and on interrupt jumps to FIFO mode */ +} lis2de12_fifo_mode_t; + +/** + * @brief LIS2DE12 FIFO config values + */ +typedef struct { + lis2de12_fifo_mode_t FIFO_mode; /**< set FIFO mode */ + uint8_t FIFO_watermark:5; /**< set the FIFO watermark level */ + bool FIFO_set_INT2; /**< sets the FIFO interrupt to INT2, otherwise INT1 */ +} lis2de12_fifo_t; + + +/** + * @brief Device descriptor for the driver + */ +typedef struct { + /** Device initialization parameters */ + lis2de12_scale_t scale; /**< sampling sensitivity used */ + lis2de12_rate_t rate; /**< sampling rate used */ + + const lis2de12_params_t *params; +} lis2de12_t; + +/** + * @brief Status and error return codes + */ +enum { + LIS2DE12_OK = 0, /**< everything was fine */ + LIS2DE12_NOBUS = -1, /**< bus interface error */ + LIS2DE12_NODEV = -2, /**< unable to talk to device */ + LIS2DE12_NOINT = -3, /**< wrong interrupt line (has to be LIS2DE12_INT1 + or LIS2DE12_INT2) */ + LIS2DE12_NODATA= -4, /**< no data available */ +}; + +/** + * @brief Initialize the given device + * + * @param[inout] dev Device descriptor of the driver + * @param[in] params Initialization parameters + * + * @return 0 on success + */ +int lis2de12_init(lis2de12_t *dev, const lis2de12_params_t *params); + +/** + * @brief Read acceleration data from the given device + * + * @param[in] dev device descriptor + * @param[out] data acceleration data in mili-g + * + * @return LIS2DE12_OK on success + * @return LIS2DE12_NOBUS on bus error + */ +int lis2de12_read(const lis2de12_t *dev, lis2de12_fifo_data_t *data); + + +int lis2de12_clear_data(const lis2de12_t *dev); + +int lis2de12_set_datarate(const lis2de12_t *dev, lis2de12_rate_t rate); +uint16_t lis2de12_get_datarate(const lis2de12_t *dev); + +int lis2de12_set_scale(lis2de12_t *dev, lis2de12_scale_t scale); +lis2de12_scale_t lis2de12_get_scale(lis2de12_t *dev); + +int lis2de12_set_fifo(const lis2de12_t *dev, const lis2de12_fifo_t *config); + +/** + * @brief Read temperature data from the given device + * + * @note The temperature sensor is not calibrated. + * Temperature values are only relative to a device specific + * reference. + * + * @param[in] dev device descriptor + * @param[out] temp temperature data in centi-°C + * + * @return LIS2DE12_OK on success + * @return LIS2DE12_NOBUS on bus error + */ +int lis2de12_read_temperature(const lis2de12_t *dev, int16_t *temp); + +#ifdef __cplusplus +} +#endif + +#endif /* LIS2DE12_H */ +/** @} */ diff --git a/drivers/lis2de12/Kconfig b/drivers/lis2de12/Kconfig new file mode 100644 index 000000000000..f0d15cd33b4e --- /dev/null +++ b/drivers/lis2de12/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2023 LIG +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. + +config MODULE_LIS2DE12 + bool "lis2de12" + depends on TEST_KCONFIG + depends on HAS_PERIPH_I2C + select MODULE_PERIPH_I2C diff --git a/drivers/lis2de12/Makefile b/drivers/lis2de12/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/drivers/lis2de12/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/lis2de12/Makefile.dep b/drivers/lis2de12/Makefile.dep new file mode 100644 index 000000000000..e67057d4639d --- /dev/null +++ b/drivers/lis2de12/Makefile.dep @@ -0,0 +1 @@ +FEATURES_REQUIRED += periph_i2c diff --git a/drivers/lis2de12/Makefile.include b/drivers/lis2de12/Makefile.include new file mode 100644 index 000000000000..382907ef1ff2 --- /dev/null +++ b/drivers/lis2de12/Makefile.include @@ -0,0 +1,2 @@ +USEMODULE_INCLUDES_lis2de12 := $(LAST_MAKEFILEDIR)/include +USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_lis2de12) diff --git a/drivers/lis2de12/include/lis2de12_constants.h b/drivers/lis2de12/include/lis2de12_constants.h new file mode 100644 index 000000000000..20f1184e49a2 --- /dev/null +++ b/drivers/lis2de12/include/lis2de12_constants.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 LIG + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_lis2de12 + * @{ + * + * @file + * @brief Internal addresses, registers and constants + * + * @author Léo + */ + +#ifndef LIS2DE12_CONSTANTS_H +#define LIS2DE12_CONSTANTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* define here the addresses, register and constants of the driver */ +#define LIS2DE12_I2C_ADDRESS (0x19) +#define LIS2DE12_I2C_DEV I2C_DEV(0) + + + + +#ifdef __cplusplus +} +#endif + +#endif /* LIS2DE12_CONSTANTS_H */ +/** @} */ diff --git a/drivers/lis2de12/include/lis2de12_params.h b/drivers/lis2de12/include/lis2de12_params.h new file mode 100644 index 000000000000..a684c6bef32e --- /dev/null +++ b/drivers/lis2de12/include/lis2de12_params.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 LIG + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_lis2de12 + * + * @{ + * @file + * @brief Default configuration + * + * @author Léo + */ + +#ifndef LIS2DE12_PARAMS_H +#define LIS2DE12_PARAMS_H + +#include "board.h" +#include "lis2de12.h" +#include "lis2de12_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Set default configuration parameters + * @{ + */ +#ifndef LIS2DE12_PARAM_I2C +#define LIS2DE12_PARAM_I2C LIS2DE12_I2C_DEV +#endif + +#ifndef LIS2DE12_PARAM_ADDR +#define LIS2DE12_PARAM_ADDR LIS2DE12_I2C_ADDRESS +#endif + +#ifndef LIS2DE12_PARAMS +#define LIS2DE12_PARAMS { \ + .i2c = LIS2DE12_PARAM_I2C, \ + .addr = LIS2DE12_PARAM_ADDR \ + } +#endif + +#ifndef LIS2DE12_PARAM_SCALE +#define LIS2DE12_PARAM_SCALE LIS2DE12_SCALE_2G +#endif +#ifndef LIS2DE12_PARAM_RATE +#define LIS2DE12_PARAM_RATE LIS2DE12_RATE_100HZ +#endif +/**@}*/ + +/** + * @brief Configuration struct + */ +static const lis2de12_params_t lis2de12_params[] = +{ + LIS2DE12_PARAMS +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LIS2DE12_PARAMS_H */ +/** @} */ diff --git a/drivers/lis2de12/include/lis2de12_registers.h b/drivers/lis2de12/include/lis2de12_registers.h new file mode 100644 index 000000000000..92d84a318d54 --- /dev/null +++ b/drivers/lis2de12/include/lis2de12_registers.h @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2023 LIG + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_lis2de12 + * @{ + * + * @file + * @brief LIS2DE12 register definitions + * + * @author Léo + */ + +#ifndef LIS2DE12_REGISTERS_H +#define LIS2DE12_REGISTERS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Definition of read Registers + * @{ + */ + +/** + * @brief STATUS_REG_AUX definitions + */ +enum { + LIS2DE12_STATUS_REG_AUX_TDA = 0x04, /**< Temperature new data available */ + LIS2DE12_STATUS_REG_AUX_TOR = 0x40, /**< Temperature data overrun */ +}; + +/** + * @brief STATUS_REG_TEMP definitions + */ +enum { + LIS2DE12_TEMP_CFG_REG_DISABLE = 0x00, /**< Temperature sensor disable */ + LIS2DE12_TEMP_CFG_REG_ENABLE = 0xC0, /**< Temperature sensor enable */ +}; + +/** + * @brief STATUS_REG definitions + */ +enum { + LIS2DE12_STATUS_REG_XDA = 0x01, /**< X-axis new data available */ + LIS2DE12_STATUS_REG_YDA = 0x02, /**< Y-axis new data available */ + LIS2DE12_STATUS_REG_ZDA = 0x04, /**< Z-axis new data available */ + LIS2DE12_STATUS_REG_ZYXDA = 0x08, /**< On X-, Y-, Z-axis new data available */ + LIS2DE12_STATUS_REG_XOR = 0x10, /**< X-axis data overrun */ + LIS2DE12_STATUS_REG_YOR = 0x20, /**< Y-axis data overrun */ + LIS2DE12_STATUS_REG_ZOR = 0x40, /**< Y-axis data overrun */ + LIS2DE12_STATUS_REG_ZYXOR = 0x80, /**< On X-, Y-, Z-axis data overrun */ +}; + +/** + * @brief INT1_SRC and INT2_SRC definitions + */ +enum { + LIS2DE12_INT_SRC_XL = 0x01, /**< X low event */ + LIS2DE12_INT_SRC_XH = 0x02, /**< X high event */ + LIS2DE12_INT_SRC_YL = 0x04, /**< Y low event */ + LIS2DE12_INT_SRC_YH = 0x08, /**< Y high event */ + LIS2DE12_INT_SRC_ZL = 0x10, /**< Z low event */ + LIS2DE12_INT_SRC_ZH = 0x20, /**< Z high event */ + LIS2DE12_INT_SRC_IA = 0x40, /**< Interrupt 1 active, at least one interrupt \ + has been generated */ +}; + +/** + * @brief Interrupt config register values + */ +enum { + LIS2DE12_INT_CFG_XLIE = 0x01, /**< enable X low event */ + LIS2DE12_INT_CFG_XHIE = 0x02, /**< enable X high event */ + LIS2DE12_INT_CFG_YLIE = 0x04, /**< enable Y low event */ + LIS2DE12_INT_CFG_YHIE = 0x08, /**< enable Y high event */ + LIS2DE12_INT_CFG_ZLIE = 0x10, /**< enable Z low event */ + LIS2DE12_INT_CFG_ZHIE = 0x20, /**< enable Z high event */ + LIS2DE12_INT_CFG_6D = 0x40, /**< enable 6-direction detection */ + LIS2DE12_INT_CFG_AOI = 0x80, /**< and/or combination interrupt events */ +}; + +/** + * @brief Interrupt type register values + */ +enum { + /* for interrupt 1 (CTRL_REG3) */ + LIS2DE12_INT_TYPE_I1_OVERRUN = 0x02, /**< FIFO overrun interrupt on INT1 */ + LIS2DE12_INT_TYPE_I1_WTM = 0x04, /**< FIFO watermark interrupt on INT1 */ + LIS2DE12_INT_TYPE_I1_ZYXDA = 0x10, /**< ZYXDA interrupt on INT1 */ + LIS2DE12_INT_TYPE_I1_IA2 = 0x20, /**< IA2 interrupt on INT1 */ + LIS2DE12_INT_TYPE_I1_IA1 = 0x40, /**< IA1 interrupt on INT1 */ + LIS2DE12_INT_TYPE_I1_CLICK = 0x80, /**< click interrupt on INT1 */ + + /* for interrupt 2 (CTRL_REG6) */ + LIS2DE12_INT_TYPE_INT_POLARITY = 0x02, /**< INT1 and INT2 pin polarity */ + LIS2DE12_INT_TYPE_I2_ACT = 0x08, /**< enable activity interrupt on INT2 */ + LIS2DE12_INT_TYPE_I2_BOOT = 0x10, /**< enable boot on INT2 */ + LIS2DE12_INT_TYPE_I2_IA2 = 0x20, /**< IA2 on INT2 */ + LIS2DE12_INT_TYPE_I2_IA1 = 0x40, /**< IA1 on INT2 */ + LIS2DE12_INT_TYPE_I2_CLICK = 0x80, /**< click interrupt on INT2 */ + + LIS2DE12_INT_TYPE_IA2 = 0x20, /**< Event 2 */ + LIS2DE12_INT_TYPE_IA1 = 0x40, /**< Event 1 */ + LIS2DE12_INT_TYPE_CLICK = 0x80, /**< click interrupt */ +}; + +/** + * @brief Event slots + */ +enum { + LIS2DE12_EVENT_1 = 0x1, /**< first event slot */ + LIS2DE12_EVENT_2 = 0x2, /**< second event slot */ + LIS2DE12_EVENT_CLICK = 0x3, /**< click event */ +}; + +/** + * @brief Extract interrupt flags for Event Slot 1 + */ +#define LIS2DE12_INT_SRC_1(ret) (((uint32_t)(ret) >> 0) & 0x7F) + +/** + * @brief Extract interrupt flags for Event Slot 2 + */ +#define LIS2DE12_INT_SRC_2(ret) (((uint32_t)(ret) >> 8) & 0x7F) + +/** + * @brief Extract interrupt flags for Click Event + */ +#define LIS2DE12_INT_SRC_CLICK(ret) (((uint32_t)(ret) >> 16) & 0x7F) + +/** + * @brief CLICK_SRC definitions + */ +typedef union { + struct { + uint8_t X_AXIS:1; /**< X click detected */ + uint8_t Y_AXIS:1; /**< Y click detected */ + uint8_t Z_AXIS:1; /**< Z click detected */ + uint8_t Sign:1; /**< Click sign, "0" positive, "1" negative */ + uint8_t SClick:1; /**< Single click detected */ + uint8_t DClick:1; /**< Double click detected */ + uint8_t IA:1; /**< Interrupt active, at least one interrupt \ + has been generated */ + uint8_t _RESERVED:1; /**< Reserved bit */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CLICK_SRC_t; + +/** + * @brief FIFO_SRC_REG definitions + */ +typedef union { + struct { + uint8_t FSS:5; /**< Number of unread samples in FIFO */ + uint8_t EMPTY:1; /**< FIFO is empty */ + uint8_t OVRN_FIFO:1; /**< Overrun in FIFO occurred */ + uint8_t WTM:1; /**< FIFO content watermark level */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_FIFO_SRC_REG_t; +/** @} */ + +/** + * + * @name Definition of read/write Registers + * @{ + */ +/** + * @brief CTRL_REG_0 definitions + */ +typedef union { + struct { + uint8_t CTRL0_DEFAULT_VALUE:7; /**< Always set this to CTRL_REG0_DEFAULT */ + uint8_t SDO_PU_DISC:1; /**< disconnect pull-up on SDO/SA0 */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CTRL_REG0_t; + +/** + * @brief TEMP_CFG_REG definitions + */ +typedef union { + struct { + uint8_t _RESERVED:6; /**< Should always be zero */ + uint8_t TEMP_EN:2; /**< "00" disables Temperature sensor, "11" enables */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_TEMP_CFG_REG_t; + +/** + * @brief CTRL_REG1 definitions + */ +typedef union { + struct { + uint8_t Xen:1; /**< X axis enable */ + uint8_t Yen:1; /**< Y axis enable */ + uint8_t Zen:1; /**< Z axis enable */ + uint8_t LPen:1; /**< Enable Low Power mode */ + uint8_t ODR:4; /**< Set Data rate */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CTRL_REG1_t; + +#define LIS2DE12_CTRL_REG2_HP_IA1 (1 << 0) +#define LIS2DE12_CTRL_REG2_HP_IA2 (1 << 1) +#define LIS2DE12_CTRL_REG2_HPCLICK (1 << 2) +#define LIS2DE12_CTRL_REG2_FDS (1 << 3) + +#define LIS2DE12_CLICK_THS_LIR (0x80) + +/** + * @brief CTRL_REG2 definitions + */ +typedef union { + struct { + uint8_t HP_IA1:1; /**< High pass filter enable for AOI on interrupt 1 */ + uint8_t HP_IA2:1; /**< High pass filter enable for AOI on interrupt 2 */ + uint8_t HPCLICK:1; /**< High pass filter enable for CLICK function */ + uint8_t FDS:1; /**< Enables filter output data */ + uint8_t HPCF:2; /**< High pass filter cutoff frequency */ + uint8_t HPM:2; /**< High pass filter mode selection */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CTRL_REG2_t; + +/** + * @brief CTRL_REG3 definitions + */ +typedef union { + struct { + uint8_t _RESERVED0:1; /**< Reserved bit */ + uint8_t I1_OVERRUN:1; /**< Enable FIFO overrun interrupt on INT1 */ + uint8_t I1_WTM:1; /**< Enable FIFO watermark interrupt on INT1 */ + uint8_t _RESERVED3:1; /**< Should always be "0" */ + uint8_t I1_ZYXDA:1; /**< Enable ZYXDA interrupt on INT1 */ + uint8_t I1_IA2:1; /**< Enable IA2 interrupt on INT1 */ + uint8_t I1_IA1:1; /**< Enable IA1 interrupt on INT1 */ + uint8_t I1_CLICK:1; /**< Enable CLICK interrupt on INT1 */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CTRL_REG3_t; + +/** + * @brief CTRL_REG4 definitions + */ +typedef union { + struct { + uint8_t SPIM:1; /**< SPI serial interface mode selection (SIM)*/ + uint8_t ST:2; /**< Self-test enable */ + uint8_t HR:1; /**< Operating mode */ + uint8_t FS:2; /**< Full-scale selection */ + uint8_t BLE:1; /**< Big/Little endian data selection */ + uint8_t BDU:1; /**< Block data update */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CTRL_REG4_t; + +/** + * @brief CTRL_REG5 definitions + */ +typedef union { + struct { + uint8_t D4D_INT2:1; /**< 4D detection enabled on INT2 */ + uint8_t LIR_INT2:1; /**< Latch interrupt request for INT2 */ + uint8_t D4D_INT1:1; /**< 4D detection enabled on INT1 */ + uint8_t LIR_INT1:1; /**< Latch interrupt request for INT2 */ + uint8_t _RESERVED:2; /**< Reserved bits */ + uint8_t FIFO_EN:1; /**< FIFO enable */ + uint8_t BOOT:1; /**< Clears the data content */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CTRL_REG5_t; + +/** + * @brief CTRL_REG6 definitions + */ +typedef union { + struct { + uint8_t _RESERVED0:1; /**< Reserved bit */ + uint8_t INT_POLARITY:1; /**< Set pin polarity for INT1 and INT2 */ + uint8_t _RESERVED2:1; /**< Reserved bit */ + uint8_t I2_ACT:1; /**< Enable activity interrupt on INT2 */ + uint8_t I2_BOOT:1; /**< Enable boot on INT2 */ + uint8_t I2_IA2:1; /**< Enable IA2 on INT2 */ + uint8_t I2_IA1:1; /**< Enable IA1 on INT2 */ + uint8_t I2_CLICK:1; /**< Enable CLICK interrupt on INT2 */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CTRL_REG6_t; + +/** + * @brief REFERENCE definitions + */ +typedef union { + uint8_t reg; /**< Set reference value */ +} LIS2DE12_REFERENCE_t; + +/** + * @brief FIFO_CTRL_REG definitions + */ +typedef union { + struct { + uint8_t FTH:5; /**< Set the watermark level for FIFO */ + uint8_t TR:1; /**< Trigging selection, FIFO event triggers INT1 or INT2 */ + uint8_t FM:2; /**< FIFO mode selection */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_FIFO_CTRL_REG_t; + +/** + * @brief INT1_CFG definitions + */ +typedef union { + struct { + uint8_t XLIE:1; /**< Enable interrupt on X low event */ + uint8_t XHIE:1; /**< Enable interrupt on X high event */ + uint8_t YLIE:1; /**< Enable interrupt on Y low event */ + uint8_t YHIE:1; /**< Enable interrupt on Y high event */ + uint8_t ZLIE:1; /**< Enable interrupt on Z low event */ + uint8_t ZHIE:1; /**< Enable interrupt on Z high event */ + uint8_t D6D:1; /**< 6 direction detection function enable */ + uint8_t AOI:1; /**< AND/OR combination of interrupt events */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_INT1_CFG_t; + +/** + * @brief INT1_THS definitions + */ +typedef union { + struct { + uint8_t THS:7; /**< Sets threshold level, the LSB changes according to + LIS2DE12_SCALE (@2G LSB=16mg; @4G LSB=32mg; @8G LSB=62mg + @16G LSB=186mg) */ + uint8_t _RESERVED:1; /**< needs to be zero */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_INT1_THS_t; + +/** + * @brief INT1_DURATION definitions + */ +typedef union { + struct { + uint8_t D:7; /**< Sets the minimum duration of INT1, in ODR cycles */ + uint8_t _RESERVED:1; /**< need to be zero */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_INT1_DURATION_t; + +/** + * @brief INT2_CFG definitions + */ +typedef union { + struct { + uint8_t XLIE:1; /**< Enable interrupt on X low event */ + uint8_t XHIE:1; /**< Enable interrupt on X high event */ + uint8_t YLIE:1; /**< Enable interrupt on Y low event */ + uint8_t YHIE:1; /**< Enable interrupt on Y high event */ + uint8_t ZLIE:1; /**< Enable interrupt on Z low event */ + uint8_t ZHIE:1; /**< Enable interrupt on Z high event */ + uint8_t D6D:1; /**< 6 direction detection function enable */ + uint8_t AOI:1; /**< AND/OR combination of interrupt events */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_INT2_CFG_t; + +/** + * @brief INT2_THS definitions + */ +typedef union { + struct { + uint8_t THS:7; /**< Sets threshold level, LSB according to LIS2DE12_SCALE */ + uint8_t _RESERVED:1; /**< needs to be zero */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_INT2_THS_t; + +/** + * @brief INT2_DURATION definitions + */ +typedef union { + struct { + uint8_t D:7; /**< Sets the minimum duration of INT2, in ODR cycles */ + uint8_t _RESERVED:1; /**< need to be zero */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_INT2_DURATION_t; + +/** + * @brief CLICK_CFG definitions + */ +typedef union { + struct { + uint8_t XS:1; /**< Interrupt single-click enable on X-axis */ + uint8_t XD:1; /**< Interrupt double-click enable on X-axis */ + uint8_t YS:1; /**< Interrupt single-click enable on Y-axis */ + uint8_t YD:1; /**< Interrupt double-click enable on Y-axis */ + uint8_t ZS:1; /**< Interrupt single-click enable on Z-axis */ + uint8_t ZD:1; /**< Interrupt double-click enable on Z-axis */ + uint8_t _RESERVED:2; /**< Reserved bits */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CLICK_CFG_t; + +/** + * @brief CLICK_THS definitions + */ +typedef union { + struct { + uint8_t THS:7; /**< Sets the click threshold, LSB according to LIS2DE12_SCALE */ + uint8_t LIR_CLICK:1; /**< Enables latency on interrupt kept high, \ + "0" for duration of latency window, \ + "1" kept high until CLICK_SRC is read */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_CLICK_THS_t; + +/** + * @brief TIME_LIMIT definitions + */ +typedef union { + struct { + uint8_t TLI:7; /**< Click time limit, in ODR cycles */ + uint8_t _RESERVED:1; /**< reserved bit */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_TIME_LIMIT_t; + +/** + * @brief TIME_LATENCY definitions + */ +typedef union { + uint8_t reg; /**< Sets time latency, in ODR cycles */ +} LIS2DE12_TIME_LATENCY_t; + +/** + * @brief TIME_WINDOW definitions + */ +typedef union { + uint8_t reg; /**< Sets time window, in ODR cycles */ +} LIS2DE12_TIME_WINDOW_t; + +/** + * @brief ACT_THS definitions + */ +typedef union { + struct { + uint8_t ACTH:7; /**< Sets the threshold sleep-to-wake or return-to-sleep + LSB according to LIS2DE12_SCALE */ + uint8_t _RESERVED:1; /**< reserved bit */ + } bit; /**< Structure used for bit access */ + uint8_t reg; /**< Type used for register access */ +} LIS2DE12_ACT_THS_t; + +/** + * @brief ACT_DURATION definitions + */ +typedef union { + uint8_t reg; /**< Sleep-to-wake and return-to-sleep duration, in ODR cycles */ +} LIS2DE12_ACT_DURATION_t; +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIS2DE12_REGISTERS_H */ +/** @} */ diff --git a/drivers/lis2de12/lis2de12.c b/drivers/lis2de12/lis2de12.c new file mode 100644 index 000000000000..d0dd2e6a7e75 --- /dev/null +++ b/drivers/lis2de12/lis2de12.c @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2023 LIG + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_lis2de12 + * @{ + * + * @file + * @brief Device driver implementation for the lis2de12 + * + * @author Léo + * + * @} + */ + +#include "assert.h" +#include "byteorder.h" +#include "mutex.h" +#include "timex.h" +#include "ztimer.h" + +#include "lis2de12.h" +#include "lis2de12_params.h" +#include "lis2de12_internal.h" +#include "lis2de12_registers.h" + + + +#define ENABLE_DEBUG 0 +#include "debug.h" + +static const uint16_t hz_per_dr[] = { + 0, /* power down */ + 1, /* Hz */ + 10, /* Hz */ + 25, /* Hz */ + 50, /* Hz */ + 100, /* Hz */ + 200, /* Hz */ + 400, /* Hz */ + 1620, /* Hz */ + 5376, /* Hz */ +}; + +//I2C functions + +/* flag for enabling address auto-incrementation */ +#define FLAG_AINC (0x80) + +static int _acquire(const lis2de12_t *dev) +{ + i2c_acquire(dev->params->i2c); + return 0; +} + +static void _release(const lis2de12_t *dev) +{ + i2c_release(dev->params->i2c); +} + +static uint8_t _read(const lis2de12_t *dev, uint8_t reg) +{ + uint8_t tmp; + i2c_read_reg(dev->params->i2c, dev->params->addr, reg, &tmp, 0); + return tmp; +} + +static void _read_burst(const lis2de12_t *dev, uint8_t reg, void *data, size_t len) +{ + i2c_read_regs(dev->params->i2c, dev->params->addr, (FLAG_AINC | reg), data, len, 0); +} + +static void _write(const lis2de12_t *dev, uint8_t reg, uint8_t data) +{ + DEBUG("[lis2de12] write: reg 0x%02x, val 0x%02x\n", (int)reg, (int)data); + i2c_write_reg(dev->params->i2c, dev->params->addr, reg, data, 0); +} + +static void _get_fifo_data(const lis2de12_t *dev, lis2de12_fifo_data_t *dst) +{ + dst->data[0] = (int16_t)((int8_t)_read(dev,REG_OUT_X_H)); + dst->data[1] = (int16_t)((int8_t)_read(dev,REG_OUT_Y_H)); + dst->data[2] = (int16_t)((int8_t)_read(dev,REG_OUT_Z_H)); + +} + +int lis2de12_init(lis2de12_t *dev, const lis2de12_params_t *params) +{ + assert(dev && params); + + dev->params = params; + + /* clear stale data */ + lis2de12_clear_data(dev); + + /* set data range */ + lis2de12_set_scale(dev, (dev->scale)); + + /* acquire the bus and verify that our parameters are valid */ + if (_acquire(dev) != 0) { + DEBUG("[lis2de12] error: unable to acquire the bus\n"); + return LIS2DE12_NOBUS; + } + + /* read the WHO_IM_I register to verify the connections to the device */ + if (_read(dev, REG_WHO_AM_I) != WHO_AM_I_VAL) { + DEBUG("[lis2de12] error: invalid value read from WHO_AM_I register\n"); + _release(dev); + return LIS2DE12_NODEV; + } + + /* clear events */ + _write(dev, REG_CTRL_REG3, 0); + _write(dev, REG_CTRL_REG6, 0); + + /* disable fifo */ + _write(dev, REG_FIFO_CTRL_REG, 0); + + /* enable all axes, set sampling rate and scale */ + LIS2DE12_CTRL_REG1_t reg1 = {0}; + + reg1.bit.ODR = dev->rate; + reg1.bit.Xen = 1; + reg1.bit.Yen = 1; + reg1.bit.Zen = 1; + + _write(dev, REG_CTRL_REG1, reg1.reg); + + /* enable block data update */ + _write(dev, REG_CTRL_REG4, 0x80); + + _release(dev); + + DEBUG("[lis2de12] initialization successful\n"); + return LIS2DE12_OK; +} + +int lis2de12_read(const lis2de12_t *dev, lis2de12_fifo_data_t *data) +{ + assert(dev); + + /* read sampled data from the device */ + _acquire(dev); + + float sensitivity = (((_read(dev, REG_CTRL_REG4) >> 4) & 0x3) + 1) * 15.6f; //0: +-2g + //1: +-4g + //2: +-8g + //3: +-16g + + + + // uint8_t comp = ((_read(dev, REG_CTRL_REG4) >> 4) & 0x3) + 2; + + /* first check if valid data is available */ + if ((_read(dev, REG_STATUS_REG) & LIS2DE12_STATUS_REG_ZYXDA) == 0) { + _release(dev); + return LIS2DE12_NODATA; + } + + ; + + _get_fifo_data(dev, data); //get raw values + + //convert to milli-g + data->axis.x *= sensitivity; + data->axis.y *= sensitivity; + data->axis.z *= sensitivity; + + + + _release(dev); + + return LIS2DE12_OK; +} + +int lis2de12_clear_data(const lis2de12_t *dev) +{ + + assert(dev); + + LIS2DE12_CTRL_REG5_t ctrl_reg5 = { + .bit.BOOT = 1, + .bit.LIR_INT1 = 1, + .bit.LIR_INT2 = 1, + }; + + _acquire(dev); + _write(dev, REG_CTRL_REG5, ctrl_reg5.reg); + _release(dev); + + return LIS2DE12_OK; +} + +int lis2de12_set_datarate(const lis2de12_t *dev, lis2de12_rate_t rate) +{ + + assert(dev); + assert(rate <= 0x9); + + LIS2DE12_CTRL_REG1_t reg1; + + _acquire(dev); + reg1.reg = _read(dev, REG_CTRL_REG1); + reg1.bit.ODR = rate; + _write(dev, REG_CTRL_REG1, reg1.reg); + _release(dev); + + return LIS2DE12_OK; +} + +uint16_t lis2de12_get_datarate(const lis2de12_t *dev) +{ + const uint16_t rates_hz[] = { + 0, + 1, + 10, + 25, + 50, + 100, + 200, + 400, + }; + + assert(dev); + + LIS2DE12_CTRL_REG1_t reg1; + + _acquire(dev); + reg1.reg = _read(dev, REG_CTRL_REG1); + _release(dev); + + if (reg1.bit.ODR < ARRAY_SIZE(rates_hz)) { + return rates_hz[reg1.bit.ODR]; + } + + if (reg1.bit.LPen) { + if (reg1.bit.ODR == 8) { + return 1620; + } + if (reg1.bit.ODR == 9) { + return 5376; + } + } + + if (reg1.bit.ODR == 9) { + return 1344; + } + + return 0; +} + +int lis2de12_set_scale(lis2de12_t *dev, lis2de12_scale_t scale) +{ + + assert(dev); + assert(scale <= LIS2DE12_SCALE_16G); + + LIS2DE12_CTRL_REG4_t reg4; + + _acquire(dev); + reg4.reg = _read(dev, REG_CTRL_REG4); + reg4.bit.FS = scale; + _write(dev, REG_CTRL_REG4, reg4.reg); + _release(dev); + + return LIS2DE12_OK; +} + +lis2de12_scale_t lis2de12_get_scale(lis2de12_t *dev) +{ + assert(dev); + + LIS2DE12_CTRL_REG4_t reg4; + + _acquire(dev); + reg4.reg = _read(dev, REG_CTRL_REG4); + _release(dev); + + return reg4.bit.FS; +} + +int lis2de12_set_fifo(const lis2de12_t *dev, const lis2de12_fifo_t *config) +{ + + assert(dev && config); + + LIS2DE12_CTRL_REG5_t reg5 = {0}; + LIS2DE12_FIFO_CTRL_REG_t fifo_reg = {0}; + + reg5.bit.LIR_INT1 = 1; + reg5.bit.LIR_INT2 = 1; + + if (config->FIFO_mode != LIS2DE12_FIFO_MODE_BYPASS) { + reg5.bit.FIFO_EN = 1; + } else { + reg5.bit.FIFO_EN = 0; + } + fifo_reg.bit.TR = config->FIFO_set_INT2; + fifo_reg.bit.FM = config->FIFO_mode; + fifo_reg.bit.FTH = config->FIFO_watermark; + + _acquire(dev); + _write(dev, REG_CTRL_REG5, reg5.reg); + _write(dev, REG_FIFO_CTRL_REG, fifo_reg.reg); + _release(dev); + + return LIS2DE12_OK; +} + +int lis2de12_read_temperature(const lis2de12_t *dev, int16_t *temp) +{ + uint8_t bytes[2]; + + _acquire(dev); + + /* enable temperature sensor */ + if (!_read(dev, REG_TEMP_CFG_REG)) { + _write(dev, REG_TEMP_CFG_REG, LIS2DE12_TEMP_CFG_REG_ENABLE); +#if IS_USED(MODULE_ZTIMER_MSEC) + uint8_t odr = _read(dev, REG_CTRL_REG1) >> 4; + ztimer_sleep(ZTIMER_MSEC, MS_PER_SEC / hz_per_dr[odr]); +#endif + } + + _read_burst(dev, REG_OUT_TEMP_L, bytes, sizeof(bytes)); + _release(dev); + + *temp = 100 * ((int16_t)bytes[1] + 25); + *temp += (100 * bytes[0]) >> 8; + + + + return 0; +} + diff --git a/drivers/lis2de12/lis2de12_internal.h b/drivers/lis2de12/lis2de12_internal.h new file mode 100644 index 000000000000..0a7a57ef3c4d --- /dev/null +++ b/drivers/lis2de12/lis2de12_internal.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2023 LIG + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup drivers_lis2de12 + * @{ + * + * @file + * @brief Command definition for the LIS2DE12 accelerometer + * + * @author Léo + */ + +#ifndef LIS2DE12_INTERNAL_H +#define LIS2DE12_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name LIS2DE12 registers + * @{ + */ +#define REG_STATUS_REG_AUX (0x07) +#define REG_OUT_TEMP_L (0x0C) +#define REG_OUT_TEMP_H (0x0D) +#define REG_WHO_AM_I (0x0F) +#define REG_CTRL_REG0 (0x1E) +#define REG_TEMP_CFG_REG (0x1F) +#define REG_CTRL_REG1 (0x20) +#define REG_CTRL_REG2 (0x21) +#define REG_CTRL_REG3 (0x22) +#define REG_CTRL_REG4 (0x23) +#define REG_CTRL_REG5 (0x24) +#define REG_CTRL_REG6 (0x25) +#define REG_REFERENCE (0x26) +#define REG_STATUS_REG (0x27) +#define REG_FIFO_READ_START (0x28) +#define REG_OUT_X_H (0x29) +#define REG_OUT_Y_H (0x2B) +#define REG_OUT_Z_H (0x2D) +#define REG_FIFO_CTRL_REG (0x2E) +#define REG_FIFO_SRC_REG (0x2F) +#define REG_INT1_CFG (0x30) +#define REG_INT1_SRC (0x31) +#define REG_INT1_THS (0x32) +#define REG_INT1_DURATION (0x33) +#define REG_INT2_CFG (0x34) +#define REG_INT2_SRC (0x35) +#define REG_INT2_THS (0x36) +#define REG_INT2_DURATION (0x37) +#define REG_CLICK_CFG (0x38) +#define REG_CLICK_SRC (0x39) +#define REG_CLICK_THS (0x3A) +#define REG_TIME_LIMIT (0x3B) +#define REG_TIME_LATENCY (0x3C) +#define REG_TIME_WINDOW (0x3D) +#define REG_ACT_THS (0x3E) +#define REG_ACT_DUR (0x3F) +/** @} */ + +/** + * @name Selected register values + * @{ + */ +#define WHO_AM_I_VAL (0x33) +#define CTRL_REG0_DEFAULT (0x10) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* LIS2DE12_INTERNAL_H */ +/** @} */ diff --git a/tests/drivers/lis2de12/Makefile b/tests/drivers/lis2de12/Makefile new file mode 100644 index 000000000000..7eb2346b590a --- /dev/null +++ b/tests/drivers/lis2de12/Makefile @@ -0,0 +1,11 @@ +include ../Makefile.drivers_common + +DRIVER ?= lis2de12 + +USEMODULE += fmt +USEMODULE += ztimer +USEMODULE += ztimer_msec +USEMODULE += shell_cmds_default +USEMODULE += $(DRIVER) + +include $(RIOTBASE)/Makefile.include diff --git a/tests/drivers/lis2de12/Makefile.ci b/tests/drivers/lis2de12/Makefile.ci new file mode 100644 index 000000000000..a6233fa0dfa7 --- /dev/null +++ b/tests/drivers/lis2de12/Makefile.ci @@ -0,0 +1,13 @@ +BOARD_INSUFFICIENT_MEMORY := \ + arduino-duemilanove \ + arduino-leonardo \ + arduino-nano \ + arduino-uno \ + atmega328p \ + atmega328p-xplained-mini \ + atmega8 \ + nucleo-f031k6 \ + nucleo-l011k4 \ + samd10-xmini \ + stm32f030f4-demo \ + # diff --git a/tests/drivers/lis2de12/README.md b/tests/drivers/lis2de12/README.md new file mode 100644 index 000000000000..5e8cbc7577c6 --- /dev/null +++ b/tests/drivers/lis2de12/README.md @@ -0,0 +1,14 @@ +# About + +This is a manual test application for the LIS2DH12 accelerometer driver. + +# Usage + +This test application will initialize the accelerometer with its default +parameters (as defined in `drivers/lis2dh12/include/lis2dh12_params.h`: + +- `LIS2DH12_PARAM_SCALE`: 100Hz +- `LIS2DH12_PARAM_RATE`: 2G + +After initialization, the sensor reads the acceleration values every 100ms +and prints them to the STDOUT. \ No newline at end of file diff --git a/tests/drivers/lis2de12/app.config.test b/tests/drivers/lis2de12/app.config.test new file mode 100644 index 000000000000..a1b4cdff76ae --- /dev/null +++ b/tests/drivers/lis2de12/app.config.test @@ -0,0 +1,9 @@ +# this file enables modules defined in Kconfig. Do not use this file for +# application configuration. This is only needed during migration. +CONFIG_MODULE_FMT=y +CONFIG_MODULE_ZTIMER=y +CONFIG_MODULE_ZTIMER_MSEC=y +CONFIG_MODULE_SHELL=y +CONFIG_MODULE_SHELL_CMDS_DEFAULT=y +CONFIG_MODULE_LIS2DE12=y + diff --git a/tests/drivers/lis2de12/main.c b/tests/drivers/lis2de12/main.c new file mode 100644 index 000000000000..ea813cd1ab15 --- /dev/null +++ b/tests/drivers/lis2de12/main.c @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2020 ML!PA Consulting GmbH + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup tests + * @{ + * + * @file + * @brief Test application for LIS2DE12 accelerometer driver + * + * @author Léo + * + * @} + */ + +#include +#include +#include +#include +#include "fmt.h" +#include "thread.h" +#include "ztimer.h" +#include "shell.h" + +#include "lis2de12.h" +#include "lis2de12_params.h" +#include "lis2de12_registers.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +/* device specific */ +#define NUM_FIFO_VALUES 32 + +/* allocate device descriptor */ +static lis2de12_t dev; + +void lis2de12_test_init(void) { + + /* init lis */ + if (lis2de12_init(&dev, &lis2de12_params[0]) == LIS2DE12_OK) { + puts("lis2de12 [Initialized]"); + } + else { + puts("lis2de12 [Failed]"); + } + + /* change LIS settings */ + lis2de12_set_datarate(&dev, LIS2DE12_RATE_100HZ); + lis2de12_set_scale(&dev, LIS2DE12_SCALE_2G); + + /* configure FIFO */ + lis2de12_fifo_t fifo_cfg = { + .FIFO_mode = LIS2DE12_FIFO_MODE_STREAM, + }; + + lis2de12_set_fifo(&dev, &fifo_cfg); +} + +static int shell_is2de12_read(int argc, char **argv) +{ + (void)argc; + (void)argv; + + + lis2de12_fifo_data_t data; + + for(int i = 1; i<= 10; i++){ + lis2de12_read(&dev, &data); + + /* Memory to print current data */ + char str_out[3][8]; + + /* format data */ + for (unsigned j = 0; j < 3; ++j) { + size_t len = fmt_s16_dfp(str_out[j], data.data[j], -3); + str_out[j][len] = '\0'; + } + + printf("measure n°%d : X: %6s g Y: %6s g Z: %6s g\n", i, str_out[0], str_out[1], str_out[2]); + + ztimer_sleep(ZTIMER_MSEC, 1000); + } + + + + return 0; +} + +static int shell_is2de12_set_rate(int argc, char **argv) +{ + unsigned rate = UINT_MAX; + + if (argc > 1) { + rate = atoi(argv[1]); + } else { + printf("Current sampling rate: %u Hz\n", lis2de12_get_datarate(&dev)); + } + + if (rate > LIS2DE12_RATE_VERYHIGH) { + printf("usage: %s \n", argv[0]); + puts("where is:"); + puts("\t1: 1 Hz"); + puts("\t2: 10 Hz"); + puts("\t3: 25 Hz"); + puts("\t4: 50 Hz"); + puts("\t5: 100 Hz"); + puts("\t6: 200 Hz"); + puts("\t7: 400 Hz"); + puts("\t8: 1620 Hz"); + puts("\t9: 5376 Hz"); + return -1; + } + + lis2de12_set_datarate(&dev, rate); + + return 0; +} + +static int shell_is2de12_set_scale(int argc, char **argv) +{ + unsigned scale = UINT_MAX; + + const uint8_t scales[] = { + 2, 4, 8, 16 + }; + + if (argc > 1) { + scale = atoi(argv[1]); + } else { + printf("current range: ± %ug\n", scales[lis2de12_get_scale(&dev)]); + } + + if (scale > LIS2DE12_SCALE_16G) { + printf("usage: %s \n", argv[0]); + puts("where is:"); + for (unsigned i = 0; i < ARRAY_SIZE(scales); ++i) { + printf("\t%u: ± %ug\n", i, scales[i]); + } + + return -1; + } + + lis2de12_set_scale(&dev, scale); + + return 0; +} + +static int shell_is2de12_read_temp(int argc, char **argv) +{ + (void)argc; + (void)argv; + + int16_t temp; + lis2de12_read_temperature(&dev, &temp); + + printf("%d.%02d °C\n", temp / 100, temp % 100); + + return 0; +} + +static const shell_command_t shell_commands[] = { + { "read", "Read acceleration data", shell_is2de12_read }, + { "rate", "Get/Set sampline rate", shell_is2de12_set_rate }, + { "scale", "Get/Set measuring range", shell_is2de12_set_scale }, + { "temp", "Read temperature data", shell_is2de12_read_temp }, + { NULL, NULL, NULL }, +}; + +int main(void) +{ + /* init lis */ + lis2de12_test_init(); + + /* running shell */ + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +}