diff --git a/boards/b-l475e-iot01a/Makefile.dep b/boards/b-l475e-iot01a/Makefile.dep index eded089b92..3598bb0d61 100644 --- a/boards/b-l475e-iot01a/Makefile.dep +++ b/boards/b-l475e-iot01a/Makefile.dep @@ -2,5 +2,6 @@ ifneq (,$(filter saul_default,$(USEMODULE))) USEMODULE += saul_gpio USEMODULE += hts221 USEMODULE += lis3mdl + USEMODULE += lps22hb USEMODULE += lsm6dsl endif diff --git a/boards/b-l475e-iot01a/include/board.h b/boards/b-l475e-iot01a/include/board.h index b7afdc3d69..d12a9b06b2 100644 --- a/boards/b-l475e-iot01a/include/board.h +++ b/boards/b-l475e-iot01a/include/board.h @@ -65,6 +65,13 @@ extern "C" { #define LIS3MDL_PARAM_I2C I2C_DEV(1) /** @} */ +/** + * @name LPS22HB pressure/temperature sensor configuration + * @{ + */ +#define LPSXXX_PARAM_I2C I2C_DEV(1) +/** @} */ + /** * @name LSM6DSL accelerometer sensor configuration * @{ diff --git a/boards/fox/include/board.h b/boards/fox/include/board.h index 6a32d1bbcd..a7ae72450d 100644 --- a/boards/fox/include/board.h +++ b/boards/fox/include/board.h @@ -56,7 +56,7 @@ extern "C" { * @name Define the interface to the LPS331AP pressure sensor * @{ */ -#define LPS331AP_PARAM_ADDR (0x5C) +#define LPSXXX_PARAM_ADDR (0x5C) /** @} */ /** diff --git a/boards/iotlab-m3/include/board.h b/boards/iotlab-m3/include/board.h index 275955e53a..c703c33f85 100644 --- a/boards/iotlab-m3/include/board.h +++ b/boards/iotlab-m3/include/board.h @@ -46,7 +46,7 @@ extern "C" { * @name Define the interface to the LPS331AP pressure sensor * @{ */ -#define LPS331AP_PARAM_ADDR (0x5C) +#define LPSXXX_PARAM_ADDR (0x5C) /** @} */ /** diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 5b327821e0..816f76666d 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -268,7 +268,11 @@ ifneq (,$(filter lpd8808,$(USEMODULE))) FEATURES_REQUIRED += periph_gpio endif -ifneq (,$(filter lps331ap,$(USEMODULE))) +ifneq (,$(filter lps331ap lps2%hb,$(USEMODULE))) + USEMODULE += lpsxxx +endif + +ifneq (,$(filter lpsxxx,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c endif diff --git a/drivers/Makefile.include b/drivers/Makefile.include index e4d4a38427..1a95698967 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -158,8 +158,8 @@ ifneq (,$(filter lpd8808,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lpd8808/include endif -ifneq (,$(filter lps331ap,$(USEMODULE))) - USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lps331ap/include +ifneq (,$(filter lpsxxx,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lpsxxx/include endif ifneq (,$(filter lsm303dlhc,$(USEMODULE))) diff --git a/drivers/include/lps331ap.h b/drivers/include/lps331ap.h deleted file mode 100644 index 0e7c5908d0..0000000000 --- a/drivers/include/lps331ap.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * 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_lps331ap LPS331AP Pressure Sensor Driver - * @ingroup drivers_sensors - * @ingroup drivers_saul - * @brief Device driver for the LPS331AP pressure sensor - * - * This driver provides @ref drivers_saul capabilities. - * @{ - * - * @file - * @brief Device driver interface for the LPS331AP pressure sensor - * - * @note This driver uses the sensors I2C interface - * - * @author Hauke Petersen - */ - -#ifndef LPS331AP_H -#define LPS331AP_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "periph/i2c.h" - - /** - * @brief The sensors default I2C address - */ -#define LPS331AP_DEFAULT_ADDRESS (0x5c) - -/** - * @brief Possible sampling rates for LPS331AP sensors - */ -typedef enum { - LPS331AP_RATE_1HZ = 1, /**< sample with 1Hz */ - LPS331AP_RATE_7HZ = 5, /**< sample with 7Hz */ - LPS331AP_RATE_12HZ5 = 6, /**< sample with 12.5Hz */ - LPS331AP_RATE_25HZ = 7 /**< sample with 25Hz */ -} lps331ap_rate_t; - -/** - * @brief Struct holding all parameters needed for device initialization - */ -typedef struct { - i2c_t i2c; /**< I2C bus the sensor is connected to */ - uint8_t addr; /**< the devices address on the bus */ - lps331ap_rate_t rate; /**< tell sensor to sample with this rate */ -} lps331ap_params_t; - -/** - * @brief Device descriptor for LPS331AP sensors - */ -typedef struct { - lps331ap_params_t params; /**< device initialization parameters */ -} lps331ap_t; - -/** - * @brief Initialize a given LPS331AP pressure sensor - * - * @param[out] dev device descriptor of the sensor - * @param[in] params initialization parameters - * - * @return 0 on success - * @return -1 on error - */ -int lps331ap_init(lps331ap_t *dev, const lps331ap_params_t * params); - -/** - * @brief Read a temperature value from the given sensor, returned in m°C - * - * @param[in] dev device descriptor of sensor to read from - * - * @return temperature value in m°C - */ -int lps331ap_read_temp(const lps331ap_t *dev); - -/** - * @brief Read a pressure value from the given sensor, returned in mbar - * - * @param[in] dev device descriptor of sensor to read from - * - * @return pressure value in mbar - */ -int lps331ap_read_pres(const lps331ap_t *dev); - -/** - * @brief Enable the given sensor - * - * @param[in] dev device descriptor of sensor to enable - * - * @return 0 on success - * @return <0 on error - */ -int lps331ap_enable(const lps331ap_t *dev); - -/** - * @brief Disable the given sensor - * - * @param[in] dev device descriptor of sensor to disable - * - * @return 0 on success - * @return <0 on error - */ -int lps331ap_disable(const lps331ap_t *dev); - -#ifdef __cplusplus -} -#endif - -#endif /* LPS331AP_H */ -/** @} */ diff --git a/drivers/include/lpsxxx.h b/drivers/include/lpsxxx.h new file mode 100644 index 0000000000..9736302e25 --- /dev/null +++ b/drivers/include/lpsxxx.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * 2018 Inria + * + * 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_lpsxxx LPS331AP/LPS25HB/LPS22HB Pressure Sensors Driver + * @ingroup drivers_sensors + * @ingroup drivers_saul + * @brief Device driver for the LPSXXX pressure sensor family (LPS331AP/LPS25HB/LPS22HB) + * + * This driver provides @ref drivers_saul capabilities. + * + * @note This driver uses the sensors I2C interface + * + * @{ + * + * @file + * + * + * @author Hauke Petersen + * @author Alexandre Abadie + */ + +#ifndef LPSXXX_H +#define LPSXXX_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "periph/i2c.h" + +/** + * @brief The sensors default I2C address + * + * Default address corresponds to SDO/SA0 pad connected to ground. If SDO/SA0 + * pad is connected to power supply, I2C address is 0x5C. + */ +#define LPSXXX_DEFAULT_ADDRESS (0x5d) + +/** + * @brief Return codes + */ +enum { + LPSXXX_OK, /**< Everything was fine */ + LPSXXX_ERR_NODEV, /**< No valid device found */ + LPSXXX_ERR_I2C, /**< An error occurred on the I2C bus */ +}; + +/** + * @brief Possible sampling rates for LPS331AP sensors + */ +typedef enum { + LPSXXX_RATE_1HZ = 1, /**< sample with 1Hz */ +#if MODULE_LPS331AP + LPSXXX_RATE_7HZ = 5, /**< sample with 7Hz, default */ + LPSXXX_RATE_12HZ5 = 6, /**< sample with 12.5Hz */ + LPSXXX_RATE_25HZ = 7 /**< sample with 25Hz */ +#elif MODULE_LPS25HB + LPSXXX_RATE_7HZ = 2, /**< sample with 7Hz, default */ + LPSXXX_RATE_12HZ5 = 3, /**< sample with 12.5Hz */ + LPSXXX_RATE_25HZ = 4 /**< sample with 25Hz */ +#elif MODULE_LPS22HB + LPSXXX_RATE_10HZ = 2, /**< sample with 10Hz */ + LPSXXX_RATE_25HZ = 3, /**< sample with 25Hz, default */ + LPSXXX_RATE_50HZ = 4, /**< sample with 50Hz */ + LPSXXX_RATE_75HZ = 5 /**< sample with 75Hz */ +#endif +} lpsxxx_rate_t; + +/** + * @brief The sensors default output data rate (ODR) + */ +#if MODULE_LPS331AP || MODULE_LPS25HB +#define LPSXXX_DEFAULT_RATE (LPSXXX_RATE_7HZ) +#else /* MODULE_LPS22HB */ +#define LPSXXX_DEFAULT_RATE (LPSXXX_RATE_25HZ) +#endif + +/** + * @brief Struct holding all parameters needed for device initialization + */ +typedef struct { + i2c_t i2c; /**< I2C bus the sensor is connected to */ + uint8_t addr; /**< the devices address on the bus */ + lpsxxx_rate_t rate; /**< tell sensor to sample with this rate */ +} lpsxxx_params_t; + +/** + * @brief Device descriptor for LPSXXX sensors + */ +typedef struct { + lpsxxx_params_t params; /**< device initialization parameters */ +} lpsxxx_t; + +/** + * @brief Initialize a given LPSXXX pressure sensor + * + * @param[out] dev device descriptor of the sensor + * @param[in] params initialization parameters + * + * @return LPSXXX_OK on success + * @return -LPSXXX_ERR_NODEV if no valid device found + * @return -LPSXXX_ERR_I2C on I2C error + */ +int lpsxxx_init(lpsxxx_t *dev, const lpsxxx_params_t *params); + +/** + * @brief Read a temperature value from the given sensor, returned in c°C + * + * @param[in] dev device descriptor of sensor to read from + * @param[out] temp temperature value in c°C + * + * @return LPSXXX_OK on success + * @return -LPSXXX_ERR_I2C on I2C error + */ +int lpsxxx_read_temp(const lpsxxx_t *dev, int16_t *temp); + +/** + * @brief Read a pressure value from the given sensor, returned in hPa + * + * @param[in] dev device descriptor of sensor to read from + * @param[out] pres pressure value in hPa + * + * @return LPSXXX_OK on success + * @return -LPSXXX_ERR_I2C on I2C error + */ +int lpsxxx_read_pres(const lpsxxx_t *dev, uint16_t *pres); + +/** + * @brief Enable the given sensor + * + * @param[in] dev device descriptor of sensor to enable + * + * @return LPSXXX_OK on success + * @return -LPSXXX_ERR_I2C on I2C error + */ +int lpsxxx_enable(const lpsxxx_t *dev); + +/** + * @brief Disable the given sensor + * + * @param[in] dev device descriptor of sensor to disable + * + * @return LPSXXX_OK on success + * @return -LPSXXX_ERR_I2C on I2C error + */ +int lpsxxx_disable(const lpsxxx_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* LPSXXX_H */ +/** @} */ diff --git a/drivers/lps331ap/include/lps331ap-internal.h b/drivers/lps331ap/include/lps331ap-internal.h deleted file mode 100644 index cee39dc160..0000000000 --- a/drivers/lps331ap/include/lps331ap-internal.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * 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_lps331ap - * @{ - * - * @file - * @brief Definitions for the LPS331AP pressure sensor - * - * @author Hauke Petersen - */ - -#ifndef LPS331AP_INTERNAL_H -#define LPS331AP_INTERNAL_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name LPS331AP registers - * @{ - */ -#define LPS331AP_AUTO_INC 0x80 -#define LPS331AP_REG_REF_P_XL 0x08 -#define LPS331AP_REG_REF_P_L 0x09 -#define LPS331AP_REG_REF_P_H 0x0a -#define LPS331AP_REG_WHO_AM_I 0x0f -#define LPS331AP_REG_RES_CONF 0x10 -#define LPS331AP_REG_CTRL_REG1 0x20 -#define LPS331AP_REG_CTRL_REG2 0x21 -#define LPS331AP_REG_CTRL_REG3 0x22 -#define LPS331AP_REG_INT_CFG_REG 0x23 -#define LPS331AP_REG_INT_SOURCE_REG 0x24 -#define LPS331AP_REG_THS_P_LOW_REG 0x25 -#define LPS331AP_REG_THS_P_HIGH_REG 0x26 -#define LPS331AP_REG_STATUS_REG 0x27 -#define LPS331AP_REG_PRESS_OUT_XL 0x28 -#define LPS331AP_REG_PRESS_OUT_L 0x29 -#define LPS331AP_REG_PRESS_OUT_H 0x2a -#define LPS331AP_REG_TEMP_OUT_L 0x2b -#define LPS331AP_REG_TEMP_OUT_H 0x2c -#define LPS331AP_REG_AMP_CTRL 0x30 -/** @} */ - -/** - * @name LPS331AP CTRL_REG1 bitfields - * @{ - */ -#define LPS331AP_CTRL_REG1_PD 0x80 -#define LPS331AP_CTRL_REG1_ODR 0x70 -#define LPS331AP_CTRL_REG1_ODR_POS 4 -#define LPS331AP_CTRL_REG1_DIFF_EN 0x08 -#define LPS331AP_CTRL_REG1_DBDU 0x04 -#define LPS331AP_CTRL_REG1_DELTA_EN 0x02 -#define LPS331AP_CTRL_REG1_SIM 0x01 -/** @} */ - -#ifdef __cplusplus -} -#endif - -#endif /* LPS331AP_INTERNAL_H */ -/** @} */ diff --git a/drivers/lps331ap/include/lps331ap_params.h b/drivers/lps331ap/include/lps331ap_params.h deleted file mode 100644 index 4329f2409a..0000000000 --- a/drivers/lps331ap/include/lps331ap_params.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2017 Freie Universität Berlin - * - * 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_lps331ap - * - * @{ - * @file - * @brief Default configuration for LPS331AP devices - * - * @author Hauke Petersen - */ - -#ifndef LPS331AP_PARAMS_H -#define LPS331AP_PARAMS_H - -#include "board.h" -#include "lps331ap.h" -#include "saul_reg.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name Set default configuration parameters - * @{ - */ -#ifndef LPS331AP_PARAM_I2C -#define LPS331AP_PARAM_I2C I2C_DEV(0) -#endif -#ifndef LPS331AP_PARAM_ADDR -#define LPS331AP_PARAM_ADDR (0x44) -#endif -#ifndef LPS331AP_PARAM_RATE -#define LPS331AP_PARAM_RATE (LPS331AP_RATE_7HZ) -#endif - -#ifndef LPS331AP_PARAMS -#define LPS331AP_PARAMS { .i2c = LPS331AP_PARAM_I2C, \ - .addr = LPS331AP_PARAM_ADDR, \ - .rate = LPS331AP_PARAM_RATE } -#endif -#ifndef LPS331AP_SAUL_INFO -#define LPS331AP_SAUL_INFO { .name = "lps331ap" } -#endif -/**@}*/ - -/** - * @brief Allocate some memory to store the actual configuration - */ -static const lps331ap_params_t lps331ap_params[] = -{ - LPS331AP_PARAMS -}; - -/** - * @brief Additional meta information to keep in the SAUL registry - */ -static const saul_reg_info_t lps331ap_saul_info[] = -{ - LPS331AP_SAUL_INFO -}; - -#ifdef __cplusplus -} -#endif - -#endif /* LPS331AP_PARAMS_H */ -/** @} */ diff --git a/drivers/lps331ap/lps331ap.c b/drivers/lps331ap/lps331ap.c deleted file mode 100644 index 83df9215b3..0000000000 --- a/drivers/lps331ap/lps331ap.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * 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_lps331ap - * @{ - * - * @file - * @brief Device driver implementation for the LPS331AP pressure sensor - * - * @note The current driver implementation is very basic and allows only for polling the - * devices temperature and pressure values. Threshold values and interrupts are not - * used. - * - * @author Hauke Petersen - * @author Peter Kietzmann - * - * @} - */ - -#include - -#include "periph/i2c.h" -#include "lps331ap.h" -#include "lps331ap-internal.h" - -/** - * @brief pressure divider for norming pressure output - */ -#define PRES_DIVIDER (4096U) - -/** - * @brief temperature base value and divider for norming temperature output - */ -#define TEMP_BASE (42.5f) -#define TEMP_DIVIDER (480U) - -#define DEV_I2C (dev->params.i2c) -#define DEV_ADDR (dev->params.addr) -#define DEV_RATE (dev->params.rate) - -int lps331ap_init(lps331ap_t *dev, const lps331ap_params_t * params) -{ - dev->params = *params; - - uint8_t tmp; - - /* Acquire exclusive access to the bus. */ - i2c_acquire(DEV_I2C); - - /* configure device, for simple operation only CTRL_REG1 needs to be touched */ - tmp = LPS331AP_CTRL_REG1_DBDU | LPS331AP_CTRL_REG1_PD | - (DEV_RATE << LPS331AP_CTRL_REG1_ODR_POS); - if (i2c_write_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_CTRL_REG1, tmp, 0) < 0) { - i2c_release(DEV_I2C); - return -1; - } - i2c_release(DEV_I2C); - - return 0; -} - -int lps331ap_read_temp(const lps331ap_t *dev) -{ - uint8_t tmp; - int16_t val = 0; - float res = TEMP_BASE; /* reference value -> see datasheet */ - - i2c_acquire(DEV_I2C); - i2c_read_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_TEMP_OUT_L, &tmp, 0); - val |= tmp; - i2c_read_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_TEMP_OUT_H, &tmp, 0); - i2c_release(DEV_I2C); - val |= ((uint16_t)tmp << 8); - - /* compute actual temperature value in °C */ - res += ((float)val) / TEMP_DIVIDER; - - /* return temperature in m°C */ - return (int)(res * 1000); -} - -int lps331ap_read_pres(const lps331ap_t *dev) -{ - uint8_t tmp; - int32_t val = 0; - float res; - - i2c_acquire(DEV_I2C); - i2c_read_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_PRESS_OUT_XL, &tmp, 0); - val |= tmp; - i2c_read_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_PRESS_OUT_L, &tmp, 0); - val |= ((uint32_t)tmp << 8); - i2c_read_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_PRESS_OUT_H, &tmp, 0); - i2c_release(DEV_I2C); - val |= ((uint32_t)tmp << 16); - /* see if value is negative */ - if (tmp & 0x80) { - val |= ((uint32_t)0xff << 24); - } - - /* compute actual pressure value in mbar */ - res = ((float)val) / PRES_DIVIDER; - - return (int)res; -} - - -int lps331ap_enable(const lps331ap_t *dev) -{ - uint8_t tmp; - int status; - - i2c_acquire(DEV_I2C); - if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_CTRL_REG1, &tmp, 0) < 0) { - i2c_release(DEV_I2C); - return -1; - } - tmp |= (LPS331AP_CTRL_REG1_PD); - status = i2c_write_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_CTRL_REG1, tmp, 0); - i2c_release(DEV_I2C); - - return status; -} - -int lps331ap_disable(const lps331ap_t *dev) -{ - uint8_t tmp; - int status; - - i2c_acquire(DEV_I2C); - if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_CTRL_REG1, &tmp, 0) < 0) { - i2c_release(DEV_I2C); - return -1; - } - tmp &= ~(LPS331AP_CTRL_REG1_PD); - status = i2c_write_reg(DEV_I2C, DEV_ADDR, LPS331AP_REG_CTRL_REG1, tmp, 0); - i2c_release(DEV_I2C); - - return status; -} diff --git a/drivers/lps331ap/lps331ap_saul.c b/drivers/lps331ap/lps331ap_saul.c deleted file mode 100644 index 913e82f8c8..0000000000 --- a/drivers/lps331ap/lps331ap_saul.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2015 Freie Universität Berlin - * - * 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_lps331ap - * @{ - * - * @file - * @brief LPS331ap adaption to the RIOT actuator/sensor interface - * - * @author Hauke Petersen - * - * @} - */ - -#include - -#include "saul.h" -#include "lps331ap.h" - -static int read_pres(const void *dev, phydat_t *res) -{ - res->val[0] = (int16_t)lps331ap_read_pres((const lps331ap_t *)dev); - res->unit = UNIT_BAR; - res->scale = -3; - return 1; -} - -static int read_temp(const void *dev, phydat_t *res) -{ - res->val[0] = (int16_t)(lps331ap_read_temp((const lps331ap_t *)dev) / 10); - res->unit = UNIT_TEMP_C; - /* above division by ten leads to °C * 10^-2*/ - res->scale = -2; - return 1; -} - -const saul_driver_t lps331ap_saul_pres_driver = { - .read = read_pres, - .write = saul_notsup, - .type = SAUL_SENSE_PRESS, -}; - -const saul_driver_t lps331ap_saul_temp_driver = { - .read = read_temp, - .write = saul_notsup, - .type = SAUL_SENSE_TEMP, -}; diff --git a/drivers/lps331ap/Makefile b/drivers/lpsxxx/Makefile similarity index 64% rename from drivers/lps331ap/Makefile rename to drivers/lpsxxx/Makefile index 318d4ab0cf..48422e909a 100644 --- a/drivers/lps331ap/Makefile +++ b/drivers/lpsxxx/Makefile @@ -1,3 +1 @@ -MODULE = lps331ap - include $(RIOTBASE)/Makefile.base diff --git a/drivers/lpsxxx/include/lpsxxx_internal.h b/drivers/lpsxxx/include/lpsxxx_internal.h new file mode 100644 index 0000000000..8aa3df662e --- /dev/null +++ b/drivers/lpsxxx/include/lpsxxx_internal.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * 2018 Inria + * + * 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_lpsxxx + * @{ + * + * @file + * @brief Definitions for the LPSXXX family of pressure sensors + * + * @author Hauke Petersen + * @author Alexandre Abadie + */ + +#ifndef LPSXXX_INTERNAL_H +#define LPSXXX_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Common LPS331AP/LPS25HB registers + * @{ + */ +#define LPSXXX_REG_WHO_AM_I (0x0f) +#define LPSXXX_REG_STATUS (0x27) +#define LPSXXX_REG_PRESS_OUT_XL (0x28) +#define LPSXXX_REG_PRESS_OUT_L (0x29) +#define LPSXXX_REG_PRESS_OUT_H (0x2a) +#define LPSXXX_REG_TEMP_OUT_L (0x2b) +#define LPSXXX_REG_TEMP_OUT_H (0x2c) +/** @} */ + +/** + * @name Common LPS331AP/LPS25HB CTRL_REG1 bitfields + * @{ + */ +#define LPSXXX_CTRL_REG1_ODR (0x70) +#define LPSXXX_CTRL_REG1_ODR_POS (4) +#define LPSXXX_CTRL_REG1_SIM (0x01) +/** @} */ + +#if MODULE_LPS331AP + +/** + * @name LPS331AP registers + * @{ + */ +#define LPSXXX_REG_REF_P_XL (0x08) +#define LPSXXX_REG_REF_P_L (0x09) +#define LPSXXX_REG_REF_P_H (0x0a) +#define LPSXXX_REG_RES_CONF (0x10) +#define LPSXXX_REG_CTRL_REG1 (0x20) +#define LPSXXX_REG_CTRL_REG2 (0x21) +#define LPSXXX_REG_CTRL_REG3 (0x22) +#define LPSXXX_REG_INT_CFG (0x23) +#define LPSXXX_REG_INT_SOURCE (0x24) +#define LPSXXX_REG_THS_P_LOW (0x25) +#define LPSXXX_REG_THS_P_HIGH (0x26) +#define LPSXXX_REG_AMP_CTRL (0x30) +/** @} */ + +/** + * @name LPS331AP CTRL_REG1 bitfields + * @{ + */ +#define LPSXXX_CTRL_REG1_PD (0x80) +#define LPSXXX_CTRL_REG1_DIFF_EN (0x08) +#define LPSXXX_CTRL_REG1_DBDU (0x04) +#define LPSXXX_CTRL_REG1_DELTA_EN (0x02) +/** @} */ + +/** + * @brief LPS331AP WHO_AM_I register value + */ +#define LPSXXX_WHO_AM_I (0xbb) + +#elif MODULE_LPS25HB + +/** + * @name LPS25HB registers + * @{ + */ +#define LPSXXX_REG_REF_P_XL (0x08) +#define LPSXXX_REG_REF_P_L (0x09) +#define LPSXXX_REG_REF_P_H (0x0a) +#define LPSXXX_REG_RES_CONF (0x10) +#define LPSXXX_REG_CTRL_REG1 (0x20) +#define LPSXXX_REG_CTRL_REG2 (0x21) +#define LPSXXX_REG_CTRL_REG3 (0x22) +#define LPSXXX_REG_CTRL_REG4 (0x23) +#define LPSXXX_REG_INT_CFG (0x24) +#define LPSXXX_REG_INT_SOURCE (0x25) +#define LPSXXX_REG_FIFO_CTRL (0x2e) +#define LPSXXX_REG_FIFO_STATUS (0x2f) +#define LPSXXX_REG_THS_P_LOW (0x30) +#define LPSXXX_REG_THS_P_HIGH (0x31) +#define LPSXXX_REG_RPDS_L (0x39) +#define LPSXXX_REG_RPDS_H (0x3a) +/** @} */ + +/** + * @name LPS25HB CTRL_REG1 bitfields + * @{ + */ +#define LPSXXX_CTRL_REG1_PD (0x80) +#define LPSXXX_CTRL_REG1_DIFF_EN (0x08) +#define LPSXXX_CTRL_REG1_BDU (0x04) +#define LPSXXX_CTRL_REG1_RESET_AZ (0x02) +/** @} */ + +/** + * @brief LPS25HB WHO_AM_I register value + */ +#define LPSXXX_WHO_AM_I (0xbd) + +#elif MODULE_LPS22HB + +/** + * @name LPS22HB registers + * @{ + */ +#define LPSXXX_REG_INT_CFG (0x0b) +#define LPSXXX_REG_THS_P_L (0x0c) +#define LPSXXX_REG_THS_P_H (0x0d) +#define LPSXXX_REG_REF_P_XL (0x15) +#define LPSXXX_REG_RES_CONF (0x1a) +#define LPSXXX_REG_CTRL_REG1 (0x10) +#define LPSXXX_REG_CTRL_REG2 (0x11) +#define LPSXXX_REG_CTRL_REG3 (0x13) +#define LPSXXX_REG_FIFO_CTRL (0x2e) +#define LPSXXX_REG_REF_P_XL (0x15) +#define LPSXXX_REG_REF_P_L (0x16) +#define LPSXXX_REG_REF_P_H (0x17) +#define LPSXXX_REG_RPDS_L (0x18) +#define LPSXXX_REG_RPDS_H (0x19) +#define LPSXXX_REG_RES_CONF (0x1a) +#define LPSXXX_REG_INT_SOURCE (0x25) +#define LPSXXX_REG_FIFO_STATUS (0x26) +#define LPSXXX_REG_LPFP_RES (0x33) +/** @} */ + +/** + * @name LPS22HB CTRL_REG1 bitfields + * @{ + */ +#define LPSXXX_CTRL_REG1_EN_LPFP (0x08) +#define LPSXXX_CTRL_REG1_LPFP_CFG (0x04) +#define LPSXXX_CTRL_REG1_BDU (0x02) +/** @} */ + +/** + * @name LPS22HB CTRL_REG2 bitfields + * @{ + */ +#define LPSXXX_CTRL_REG2_ID_ADD_INC (0x10) +/** @} */ + +/** + * @brief LPS22HB WHO_AM_I register value + */ +#define LPSXXX_WHO_AM_I (0xb1) + +#endif /* MODULE_LPS22HB */ + +#ifdef __cplusplus +} +#endif + +#endif /* LPSXXX_INTERNAL_H */ +/** @} */ diff --git a/drivers/lpsxxx/include/lpsxxx_params.h b/drivers/lpsxxx/include/lpsxxx_params.h new file mode 100644 index 0000000000..3c3f3fe4e2 --- /dev/null +++ b/drivers/lpsxxx/include/lpsxxx_params.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2017 Freie Universität Berlin + * 2018 Inria + * + * 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_lpsxxx + * + * @{ + * @file + * @brief Default configuration for LPSXXX family of devices + * + * @author Hauke Petersen + * @author Alexandre Abadie + */ + +#ifndef LPSXXX_PARAMS_H +#define LPSXXX_PARAMS_H + +#include "board.h" +#include "lpsxxx.h" +#include "saul_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Set default configuration parameters + * @{ + */ +#ifndef LPSXXX_PARAM_I2C +#define LPSXXX_PARAM_I2C I2C_DEV(0) +#endif +#ifndef LPSXXX_PARAM_ADDR +#define LPSXXX_PARAM_ADDR (LPSXXX_DEFAULT_ADDRESS) +#endif +#ifndef LPSXXX_PARAM_RATE +#define LPSXXX_PARAM_RATE (LPSXXX_DEFAULT_RATE) +#endif + +#ifndef LPSXXX_PARAMS +#define LPSXXX_PARAMS { .i2c = LPSXXX_PARAM_I2C, \ + .addr = LPSXXX_PARAM_ADDR, \ + .rate = LPSXXX_PARAM_RATE } +#endif + +#if MODULE_LPS331AP +#define LPSXXX_SAUL_NAME "lps331ap" +#elif MODULE_LPS25HB +#define LPSXXX_SAUL_NAME "lps25hb" +#elif MODULE_LPS22HB +#define LPSXXX_SAUL_NAME "lps22hb" +#endif +#ifndef LPSXXX_SAUL_INFO +#define LPSXXX_SAUL_INFO { .name = LPSXXX_SAUL_NAME } +#endif +/**@}*/ + +/** + * @brief Allocate some memory to store the actual configuration + */ +static const lpsxxx_params_t lpsxxx_params[] = +{ + LPSXXX_PARAMS +}; + +/** + * @brief Additional meta information to keep in the SAUL registry + */ +static const saul_reg_info_t lpsxxx_saul_info[] = +{ + LPSXXX_SAUL_INFO +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LPSXXX_PARAMS_H */ +/** @} */ diff --git a/drivers/lpsxxx/lpsxxx.c b/drivers/lpsxxx/lpsxxx.c new file mode 100644 index 0000000000..d40f70ef2a --- /dev/null +++ b/drivers/lpsxxx/lpsxxx.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * 2018 Inria + * + * 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_lpsxxx + * @{ + * + * @file + * @brief Device driver implementation for the LPSXXX family of pressure sensors + * + * @note The current driver implementation is very basic and allows only for polling the + * devices temperature and pressure values. Threshold values and interrupts are not + * used. + * + * @author Hauke Petersen + * @author Peter Kietzmann + * @author Alexandre Abadie + * + * @} + */ + +#include + +#include "periph/i2c.h" +#include "lpsxxx.h" +#include "lpsxxx_internal.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +/** + * @brief pressure divider for norming pressure output + */ +#define PRES_DIVIDER (12U) + +/** + * @brief temperature base value and divider for norming temperature output + */ +#if MODULE_LPS331AP || MODULE_LPS25HB +#define TEMP_BASE (42.5f) +#define TEMP_DIVIDER (480U) +#else +#define TEMP_BASE (0.0f) +#define TEMP_DIVIDER (100U) +#endif + +#define DEV_I2C (dev->params.i2c) +#define DEV_ADDR (dev->params.addr) +#define DEV_RATE (dev->params.rate) + +int lpsxxx_init(lpsxxx_t *dev, const lpsxxx_params_t * params) +{ + dev->params = *params; + + /* Acquire exclusive access to the bus. */ + i2c_acquire(DEV_I2C); + uint8_t id; + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_WHO_AM_I, &id, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] init: cannot read WHO_AM_I register\n"); + return -LPSXXX_ERR_I2C; + } + + if (id != LPSXXX_WHO_AM_I) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] init: not a valid device (got %02X, expected %02X)\n", + id, LPSXXX_WHO_AM_I); + return -LPSXXX_ERR_NODEV; + } + + uint8_t tmp; + +#if MODULE_LPS22HB + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_CTRL_REG2, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] init: cannot read LPSXXX_REG_CTRL_REG2 register\n"); + return -LPSXXX_ERR_I2C; + } + + /* Disable automatic increment of register address during byte access + (recommanded in datasheet (section 9.6 CTRL_REG2) */ + tmp &= ~LPSXXX_CTRL_REG2_ID_ADD_INC; + + DEBUG("[lpsxxx] init: update reg2, %02X\n", tmp); + + if (i2c_write_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_CTRL_REG2, tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] init: cannot write in CTRL_REG2 register\n"); + return -LPSXXX_ERR_I2C; + } +#endif + + /* configure device, for simple operation only CTRL_REG1 needs to be touched */ +#if MODULE_LPS331AP + tmp = LPSXXX_CTRL_REG1_DBDU | LPSXXX_CTRL_REG1_PD | + (DEV_RATE << LPSXXX_CTRL_REG1_ODR_POS); +#elif MODULE_LPS25HB + tmp = LPSXXX_CTRL_REG1_BDU | LPSXXX_CTRL_REG1_PD | + (DEV_RATE << LPSXXX_CTRL_REG1_ODR_POS); +#elif MODULE_LPS22HB + tmp = LPSXXX_CTRL_REG1_EN_LPFP | /* Low-pass filter configuration: ODR/9 */ + LPSXXX_CTRL_REG1_BDU | (DEV_RATE << LPSXXX_CTRL_REG1_ODR_POS); +#endif + + DEBUG("[lpsxxx] init: update reg1, value: %02X\n", tmp); + + if (i2c_write_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_CTRL_REG1, tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] init: cannot write in CTRL_REG1 register\n"); + return -LPSXXX_ERR_I2C; + } + + i2c_release(DEV_I2C); + + DEBUG("[lpsxxx] initialization successful\n"); + return LPSXXX_OK; +} + +int lpsxxx_read_temp(const lpsxxx_t *dev, int16_t *temp) +{ + uint8_t tmp; + int16_t val = 0; + float res = TEMP_BASE; /* reference value -> see datasheet */ + + i2c_acquire(DEV_I2C); + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_TEMP_OUT_L, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] read_temp: cannot read TEMP_OUT_L register\n"); + return -LPSXXX_ERR_I2C; + } + val |= tmp; + + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_TEMP_OUT_H, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] read_temp: cannot read TEMP_OUT_H register\n"); + return -LPSXXX_ERR_I2C; + } + i2c_release(DEV_I2C); + val |= ((uint16_t)tmp << 8); + + DEBUG("[lpsxxx] read_temp: raw data %08" PRIx32 "\n", (uint32_t)val); + + /* compute actual temperature value in °C */ + res += ((float)val) / TEMP_DIVIDER; + + /* return temperature in c°C */ + *temp = (int16_t)(res * 100); + return LPSXXX_OK; +} + +int lpsxxx_read_pres(const lpsxxx_t *dev, uint16_t *pres) +{ + uint8_t tmp; + int32_t val = 0; + + i2c_acquire(DEV_I2C); + + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_PRESS_OUT_XL, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] read_pres: cannot read PRES_OUT_XL register\n"); + return -LPSXXX_ERR_I2C; + } + val |= tmp; + + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_PRESS_OUT_L, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] read_pres: cannot read PRES_OUT_L register\n"); + return -LPSXXX_ERR_I2C; + } + val |= ((uint32_t)tmp << 8); + + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_PRESS_OUT_H, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] read_pres: cannot read PRES_OUT_H register\n"); + return -LPSXXX_ERR_I2C; + } + i2c_release(DEV_I2C); + + val |= ((uint32_t)tmp << 16); + + DEBUG("[lpsxxx] read_pres: raw data %08" PRIx32 "\n", (uint32_t)val); + + /* see if value is negative */ + if (tmp & 0x80) { + val |= ((uint32_t)0xff << 24); + } + + /* compute actual pressure value in hPa */ + *pres = (uint16_t)(val >> PRES_DIVIDER); + + return LPSXXX_OK; +} + +int lpsxxx_enable(const lpsxxx_t *dev) +{ + uint8_t tmp; + + i2c_acquire(DEV_I2C); + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_CTRL_REG1, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] enable: cannot read CTRL_REG1 register\n"); + return -LPSXXX_ERR_I2C; + } +#if MODULE_LPS331AP || MODULE_LPS25HB + tmp |= LPSXXX_CTRL_REG1_PD; +#else + tmp |= LPSXXX_CTRL_REG1_EN_LPFP | /* Low-pass filter configuration: ODR/9 */ + LPSXXX_CTRL_REG1_BDU | (DEV_RATE << LPSXXX_CTRL_REG1_ODR_POS); +#endif + + + DEBUG("[lpsxxx] enable: update reg1 with %02X\n", tmp); + + if (i2c_write_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_CTRL_REG1, tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] enable: cannot write CTRL_REG1 register\n"); + return -LPSXXX_ERR_I2C; + } + i2c_release(DEV_I2C); + + return LPSXXX_OK; +} + +int lpsxxx_disable(const lpsxxx_t *dev) +{ + uint8_t tmp; + + i2c_acquire(DEV_I2C); + if (i2c_read_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_CTRL_REG1, &tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] disable: cannot read CTRL_REG1 register\n"); + return -LPSXXX_ERR_I2C; + } +#if MODULE_LPS331AP || MODULE_LPS25HB + tmp &= ~LPSXXX_CTRL_REG1_PD; +#else + tmp &= ~(7 << LPSXXX_CTRL_REG1_ODR_POS); +#endif + + DEBUG("[lpsxxx] disable: update reg1 with %02X\n", tmp); + + if (i2c_write_reg(DEV_I2C, DEV_ADDR, LPSXXX_REG_CTRL_REG1, tmp, 0) < 0) { + i2c_release(DEV_I2C); + DEBUG("[lpsxxx] disable: cannot write CTRL_REG1 register\n"); + return -LPSXXX_ERR_I2C; + } + i2c_release(DEV_I2C); + + return LPSXXX_OK; +} diff --git a/drivers/lpsxxx/lpsxxx_saul.c b/drivers/lpsxxx/lpsxxx_saul.c new file mode 100644 index 0000000000..30d200e14d --- /dev/null +++ b/drivers/lpsxxx/lpsxxx_saul.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * 2018 Inria + * + * 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_lpsxxx + * @{ + * + * @file + * @brief LPSXXX (LPS331ap/LPS25HB/LPS22HB) adaption to SAUL interface + * + * @author Hauke Petersen + * @author Alexandre Abadie + * + * @} + */ + +#include + +#include "saul.h" +#include "lpsxxx.h" + +static int read_pres(const void *dev, phydat_t *res) +{ + if (lpsxxx_read_pres((const lpsxxx_t *)dev, (uint16_t *)&res->val[0]) == LPSXXX_OK) { + res->unit = UNIT_PA; + res->scale = 2; + return 1; + } + + return -ECANCELED; +} + +static int read_temp(const void *dev, phydat_t *res) +{ + if (lpsxxx_read_temp((const lpsxxx_t *)dev, &res->val[0]) == LPSXXX_OK) { + res->unit = UNIT_TEMP_C; + res->scale = -2; + return 1; + } + + return -ECANCELED; +} + +const saul_driver_t lpsxxx_saul_pres_driver = { + .read = read_pres, + .write = saul_notsup, + .type = SAUL_SENSE_PRESS, +}; + +const saul_driver_t lpsxxx_saul_temp_driver = { + .read = read_temp, + .write = saul_notsup, + .type = SAUL_SENSE_TEMP, +}; diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 6b2b3b290e..1dcfede6f2 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -118,6 +118,11 @@ PSEUDOMODULES += vcnl4010 PSEUDOMODULES += vcnl4020 PSEUDOMODULES += vcnl4040 +# include variants of lpsxxx drivers as pseudo modules +PSEUDOMODULES += lps331ap +PSEUDOMODULES += lps22hb +PSEUDOMODULES += lps25hb + # add all pseudo random number generator variants as pseudomodules PSEUDOMODULES += prng_% diff --git a/sys/auto_init/auto_init.c b/sys/auto_init/auto_init.c index 2f8c9f6be8..e94d530d75 100644 --- a/sys/auto_init/auto_init.c +++ b/sys/auto_init/auto_init.c @@ -409,9 +409,9 @@ void auto_init(void) extern void auto_init_lis3mdl(void); auto_init_lis3mdl(); #endif -#ifdef MODULE_LPS331AP - extern void auto_init_lps331ap(void); - auto_init_lps331ap(); +#ifdef MODULE_LPSXXX + extern void auto_init_lpsxxx(void); + auto_init_lpsxxx(); #endif #ifdef MODULE_LSM303DLHC extern void auto_init_lsm303dlhc(void); diff --git a/sys/auto_init/saul/auto_init_lps331ap.c b/sys/auto_init/saul/auto_init_lps331ap.c deleted file mode 100644 index c1725c0bb2..0000000000 --- a/sys/auto_init/saul/auto_init_lps331ap.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2015 Freie Universität Berlin - * - * 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 sys_auto_init_saul - * @{ - * - * @file - * @brief Auto initialization of LPS331AP pressure sensors - * - * @author Hauke Petersen - * - * @} - */ - -#ifdef MODULE_LPS331AP - -#include "assert.h" -#include "log.h" -#include "saul_reg.h" -#include "lps331ap.h" -#include "lps331ap_params.h" - -/** - * @brief Define the number of configured sensors - */ -#define LPS331AP_NUM (sizeof(lps331ap_params) / sizeof(lps331ap_params[0])) - -/** - * @brief Allocate memory for the device descriptors - */ -static lps331ap_t lps331ap_devs[LPS331AP_NUM]; - -/** - * @brief Memory for the SAUL registry entries - */ -static saul_reg_t saul_entries[LPS331AP_NUM * 2]; - -/** - * @brief Define the number of saul info - */ -#define LPS331AP_INFO_NUM (sizeof(lps331ap_saul_info) / sizeof(lps331ap_saul_info[0])) - -/** - * @brief Reference the driver struct - */ -extern saul_driver_t lps331ap_saul_pres_driver; -extern saul_driver_t lps331ap_saul_temp_driver; - - -void auto_init_lps331ap(void) -{ - assert(LPS331AP_NUM == LPS331AP_INFO_NUM); - - for (unsigned int i = 0; i < LPS331AP_NUM; i++) { - LOG_DEBUG("[auto_init_saul] initializing lps331ap #%u\n", i); - - if (lps331ap_init(&lps331ap_devs[i], &lps331ap_params[i]) < 0) { - LOG_ERROR("[auto_init_saul] error initializing lps331ap #%u\n", i); - continue; - } - - saul_entries[i].dev = &(lps331ap_devs[i]); - saul_entries[i].name = lps331ap_saul_info[i].name; - saul_entries[i].driver = &lps331ap_saul_pres_driver; - saul_reg_add(&(saul_entries[i])); - saul_entries[(i * 2) + 1].dev = &(lps331ap_devs[i]); - saul_entries[(i * 2) + 1].name = lps331ap_saul_info[i].name; - saul_entries[(i * 2) + 1].driver = &lps331ap_saul_temp_driver; - saul_reg_add(&(saul_entries[(i * 2) + 1])); - } -} - -#else -typedef int dont_be_pedantic; -#endif /* MODULE_LPS331AP */ diff --git a/sys/auto_init/saul/auto_init_lpsxxx.c b/sys/auto_init/saul/auto_init_lpsxxx.c new file mode 100644 index 0000000000..5a190cff48 --- /dev/null +++ b/sys/auto_init/saul/auto_init_lpsxxx.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * 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 sys_auto_init_saul + * @{ + * + * @file + * @brief Auto initialization of LPSXXX family of pressure sensors + * + * @author Hauke Petersen + * + * @} + */ + +#ifdef MODULE_LPSXXX + +#include "assert.h" +#include "log.h" +#include "saul_reg.h" +#include "lpsxxx.h" +#include "lpsxxx_params.h" + +/** + * @brief Define the number of configured sensors + */ +#define LPSXXX_NUM (sizeof(lpsxxx_params) / sizeof(lpsxxx_params[0])) + +/** + * @brief Allocate memory for the device descriptors + */ +static lpsxxx_t lpsxxx_devs[LPSXXX_NUM]; + +/** + * @brief Memory for the SAUL registry entries + */ +static saul_reg_t saul_entries[LPSXXX_NUM * 2]; + +/** + * @brief Define the number of saul info + */ +#define LPSXXX_INFO_NUM (sizeof(lpsxxx_saul_info) / sizeof(lpsxxx_saul_info[0])) + +/** + * @brief Reference the driver struct + */ +extern saul_driver_t lpsxxx_saul_pres_driver; +extern saul_driver_t lpsxxx_saul_temp_driver; + + +void auto_init_lpsxxx(void) +{ + assert(LPSXXX_NUM == LPSXXX_INFO_NUM); + + for (unsigned int i = 0; i < LPSXXX_NUM; i++) { + LOG_DEBUG("[auto_init_saul] initializing %s #%u\n", + LPSXXX_SAUL_NAME, i); + + if (lpsxxx_init(&lpsxxx_devs[i], &lpsxxx_params[i]) < 0) { + LOG_ERROR("[auto_init_saul] error initializing %s #%u\n", + LPSXXX_SAUL_NAME, i); + continue; + } + + saul_entries[i].dev = &(lpsxxx_devs[i]); + saul_entries[i].name = lpsxxx_saul_info[i].name; + saul_entries[i].driver = &lpsxxx_saul_pres_driver; + saul_reg_add(&(saul_entries[i])); + saul_entries[(i * 2) + 1].dev = &(lpsxxx_devs[i]); + saul_entries[(i * 2) + 1].name = lpsxxx_saul_info[i].name; + saul_entries[(i * 2) + 1].driver = &lpsxxx_saul_temp_driver; + saul_reg_add(&(saul_entries[(i * 2) + 1])); + } +} + +#else +typedef int dont_be_pedantic; +#endif /* MODULE_LPSXXX */ diff --git a/tests/driver_lps331ap/README.md b/tests/driver_lps331ap/README.md deleted file mode 100644 index 96daac3736..0000000000 --- a/tests/driver_lps331ap/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# About -This is a manual test application for the LPS331AP pressure sensor driver. - -# Usage -This test application will initialize the pressure sensor with the following parameters: - - Sampling Rate: 7Hz - -After initialization, the sensor reads the pressure and temperature values every 250ms -and prints them to the STDOUT. diff --git a/tests/driver_lps331ap/main.c b/tests/driver_lps331ap/main.c deleted file mode 100644 index 746aea02c9..0000000000 --- a/tests/driver_lps331ap/main.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * 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 the LPS331AP pressure sensor - * - * @author Hauke Petersen - * - * @} - */ - -#include - -#include "xtimer.h" -#include "lps331ap.h" -#include "lps331ap_params.h" - -#define SLEEP (250 * 1000U) - -int main(void) -{ - lps331ap_t dev; - - puts("LPS331AP pressure sensor test application\n"); - puts("Initializing LPS331AP sensor"); - if (lps331ap_init(&dev, &lps331ap_params[0]) == 0) { - puts("[OK]\n"); - } - else { - puts("[Failed]"); - return 1; - } - - while (1) { - int pres = lps331ap_read_pres(&dev); - int temp = lps331ap_read_temp(&dev); - - int pres_abs = pres / 1000; - pres -= pres_abs * 1000; - int temp_abs = temp / 1000; - temp -= temp_abs * 1000; - - printf("Pressure value: %2i.%03i bar - Temperature: %2i.%03i °C\n", - pres_abs, pres, temp_abs, temp); - - xtimer_usleep(SLEEP); - } - - return 0; -} diff --git a/tests/driver_lps331ap/Makefile b/tests/driver_lpsxxx/Makefile similarity index 68% rename from tests/driver_lps331ap/Makefile rename to tests/driver_lpsxxx/Makefile index 3099ea5cd4..9664dc9003 100644 --- a/tests/driver_lps331ap/Makefile +++ b/tests/driver_lpsxxx/Makefile @@ -1,6 +1,8 @@ include ../Makefile.tests_common -USEMODULE += lps331ap +DRIVER ?= lps331ap + +USEMODULE += $(DRIVER) USEMODULE += xtimer include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_lpsxxx/README.md b/tests/driver_lpsxxx/README.md new file mode 100644 index 0000000000..0a73aaf2c6 --- /dev/null +++ b/tests/driver_lpsxxx/README.md @@ -0,0 +1,17 @@ +# About + +This is a manual test application for the LPSXXX family of pressure sensors +driver. This driver can be used with LPS331AP, LPS25HB and LPS22HB. + +Default driver is `lps331ap`. To use the LPS25HB driver, set the `DRIVER` when +building the application: + + DRIVER=lps25hb make BOARD= + +# Usage + +This test application will initialize the pressure sensor with a sampling rate +of 7Hz (25Hz with lps22hb). + +After initialization, the sensor reads the pressure and temperature values +every 250ms and prints them to the STDOUT. diff --git a/tests/driver_lpsxxx/main.c b/tests/driver_lpsxxx/main.c new file mode 100644 index 0000000000..e251ccc727 --- /dev/null +++ b/tests/driver_lpsxxx/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * 2018 Inria + * + * 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 the LPS331AP/LPS25HB/LPS22HB pressure sensor + * + * @author Hauke Petersen + * @author Alexandre Abadie + * + * @} + */ + +#include + +#include "xtimer.h" +#include "lpsxxx.h" +#include "lpsxxx_params.h" + +int main(void) +{ + lpsxxx_t dev; + + printf("Test application for %s pressure sensor\n\n", LPSXXX_SAUL_NAME); + printf("Initializing %s sensor\n", LPSXXX_SAUL_NAME); + if (lpsxxx_init(&dev, &lpsxxx_params[0]) != LPSXXX_OK) { + puts("Initialization failed"); + return 1; + } + + uint16_t pres; + int16_t temp; + while (1) { + lpsxxx_enable(&dev); + xtimer_sleep(1); /* wait a bit for the measurements to complete */ + + lpsxxx_read_temp(&dev, &temp); + lpsxxx_read_pres(&dev, &pres); + lpsxxx_disable(&dev); + + int temp_abs = temp / 100; + temp -= temp_abs * 100; + + printf("Pressure value: %ihPa - Temperature: %2i.%02i°C\n", + pres, temp_abs, temp); + } + + return 0; +}