From 3a6a3b8b143ca741ada6f88d69fdb79261ac817b Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Thu, 23 Mar 2017 14:11:44 +0100 Subject: [PATCH] drivers/si114x: initial basic support --- drivers/Makefile.dep | 6 + drivers/Makefile.include | 4 + drivers/include/si114x.h | 141 +++++++++++ drivers/si114x/Makefile | 1 + drivers/si114x/include/si114x_internals.h | 207 ++++++++++++++++ drivers/si114x/include/si114x_params.h | 69 ++++++ drivers/si114x/si114x.c | 272 ++++++++++++++++++++++ drivers/si114x/si114x_saul.c | 89 +++++++ makefiles/pseudomodules.inc.mk | 5 + 9 files changed, 794 insertions(+) create mode 100644 drivers/include/si114x.h create mode 100644 drivers/si114x/Makefile create mode 100644 drivers/si114x/include/si114x_internals.h create mode 100644 drivers/si114x/include/si114x_params.h create mode 100644 drivers/si114x/si114x.c create mode 100644 drivers/si114x/si114x_saul.c diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index de911d403b..bb24f336e2 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -280,6 +280,12 @@ ifneq (,$(filter sht11,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter si114%,$(USEMODULE))) + USEMODULE += xtimer + FEATURES_REQUIRED += periph_i2c + USEMODULE += si114x +endif + ifneq (,$(filter si70%,$(USEMODULE))) USEMODULE += xtimer FEATURES_REQUIRED += periph_i2c diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 03b3308775..4f6c8687e6 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -190,6 +190,10 @@ ifneq (,$(filter sdcard_spi,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/sdcard_spi/include endif +ifneq (,$(filter si114x,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/si114x/include +endif + ifneq (,$(filter si70xx,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/si70xx/include endif diff --git a/drivers/include/si114x.h b/drivers/include/si114x.h new file mode 100644 index 0000000000..828d7192c1 --- /dev/null +++ b/drivers/include/si114x.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2016-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_si114x Si1145/6/7 UV/Ambient light/Proximity sensors + * @ingroup drivers_sensors + * @brief Device driver for the Si1145/6/7 sensors family + * @{ + * + * @file + * @brief Device driver interface for the Si114x sensors family + * + * @author Alexandre Abadie + * Bas Stottelaar + */ + +#ifndef SI114X_H +#define SI114X_H + +#include "saul.h" +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialization return codes + */ +typedef enum { + SI114X_OK, + SI114X_ERR_I2C, + SI114X_ERR_NODEV +} si114x_ret_code_t; + +/** + * @brief Active LED current parameters + */ +typedef enum { + SI114X_PS_LED1 = 1, /**< 5.6mA */ + SI114X_PS_LED2, /**< 11.2mA */ + SI114X_PS_LED3, /**< 22.4mA */ + SI114X_PS_LED4, /**< 45mA */ + SI114X_PS_LED5, /**< 67mA */ + SI114X_PS_LED6, /**< 90mA */ + SI114X_PS_LED7, /**< 112mA */ + SI114X_PS_LED8, /**< 135mA */ + SI114X_PS_LED9, /**< 157mA */ + SI114X_PS_LED10, /**< 180mA */ + SI114X_PS_LED11, /**< 202mA */ + SI114X_PS_LED12, /**< 224mA */ + SI114X_PS_LED13, /**< 269mA */ + SI114X_PS_LED14, /**< 314mA */ + SI114X_PS_LED15 /**< 359mA */ +} si114x_led_current_t; + +/** + * @brief Device initialization parameters + */ +typedef struct { + i2c_t i2c_dev; /**< I2C device which is used */ + si114x_led_current_t led_current; /**< Proximity LED current */ +} si114x_params_t; + + +/** + * @brief Device descriptor for the Si114x sensor + */ +typedef struct { + si114x_params_t params; /**< Si114x initialization parameters */ +} si114x_t; + +/** + * @brief Initialize the given Si114x device + * + * @param[out] dev Initialized device descriptor of Si114x device + * @param[in] params Initialization parameters + * + * @return SI114X_OK: all good + * @return -SI114X_ERR_I2C: I2C bus cannot be initialized + * @return -SI114X_ERR_NODEV: not a valid Si114x device + */ +int8_t si114x_init(si114x_t *dev, const si114x_params_t * params); + +/** + * @brief Read UV index from the given Si114x device + * + * @param[in] dev Device descriptor of Si114x device to read from + * + * @return UV index + */ +uint16_t si114x_read_uv(si114x_t *dev); + +/** + * @brief Read IR light value from the given Si114x device, returned in lx + * + * @param[in] dev Device descriptor of Si114x device to read from + * + * @return IR light in lx + */ +uint16_t si114x_read_ir(si114x_t *dev); + +/** + * @brief Read visible light value from the given Si114x device, returned in lx + * + * @param[in] dev Device descriptor of Si114x device to read from + * + * @return Visible light in lx + */ +uint16_t si114x_read_visible(si114x_t *dev); + +/** + * @brief Read distance measure from the given Si114x device, returned in ADC + * counts. + * + * @param[in] dev Device descriptor of Si114x device to read from + * + * @return Distance in ADC counts + */ +uint16_t si114x_read_distance(si114x_t *dev); + +/** + * @brief Read the response register. + * + * @param[in] dev Device descriptor of Si114x device to read from + * + * @return Device response register contents + */ +uint8_t si114x_read_response(si114x_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* SI114X_H */ +/** @} */ diff --git a/drivers/si114x/Makefile b/drivers/si114x/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/si114x/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/si114x/include/si114x_internals.h b/drivers/si114x/include/si114x_internals.h new file mode 100644 index 0000000000..bb7081b921 --- /dev/null +++ b/drivers/si114x/include/si114x_internals.h @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2016-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_si114x + * @brief Internal addresses, registers, constants for the Si114x sensors family. + * @{ + * + * @file + * @brief Internal addresses, registers, constants for the Si114x sensor. + * + * @author Alexandre Abadie + */ + +#ifndef SI114X_INTERNALS_H +#define SI114X_INTERNALS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Si114x I2C address + */ +#define SI114X_ADDR (0x60) + +/** + * @name Si114x commands + * @{ + */ +#define SI114X_PARAM_QUERY (0x80) +#define SI114X_PARAM_SET (0xA0) +#define SI114X_NOP (0x00) +#define SI114X_RESET (0x01) +#define SI114X_BUSADDR (0x02) +#define SI114X_PS_FORCE (0x05) +#define SI114X_ALS_FORCE (0x06) +#define SI114X_PS_ALS_FORCE (0x07) +#define SI114X_PS_PAUSE (0x09) +#define SI114X_ALS_PAUSE (0x0A) +#define SI114X_PS_ALS_PAUSE (0x0B) +#define SI114X_PS_AUTO (0x0D) +#define SI114X_ALS_AUTO (0x0E) +#define SI114X_PS_ALS_AUTO (0x0F) +#define SI114X_GET_CAL (0x12) +/** @} */ + +/** + * @name Si114x registers + * @{ + */ +#define SI114X_REG_PART_ID (0x00) +#define SI114X_REG_REV_ID (0x01) +#define SI114X_REG_SEQ_ID (0x02) +#define SI114X_REG_INT_CFG (0x03) +#define SI114X_REG_IRQ_ENABLE (0x04) +#define SI114X_REG_IRQ_MODE1 (0x05) +#define SI114X_REG_IRQ_MODE2 (0x06) +#define SI114X_REG_HW_KEY (0x07) +#define SI114X_REG_MEAS_RATE0 (0x08) +#define SI114X_REG_MEAS_RATE1 (0x09) +#define SI114X_REG_PS_LED21 (0x0F) +#define SI114X_REG_PS_LED3 (0x10) +#define SI114X_REG_UCOEF0 (0x13) +#define SI114X_REG_UCOEF1 (0x14) +#define SI114X_REG_UCOEF2 (0x15) +#define SI114X_REG_UCOEF3 (0x16) +#define SI114X_REG_PARAM_WR (0x17) +#define SI114X_REG_COMMAND (0x18) +#define SI114X_REG_RESPONSE (0x20) +#define SI114X_REG_IRQ_STATUS (0x21) +#define SI114X_REG_ALS_VIS_DATA0 (0x22) +#define SI114X_REG_ALS_VIS_DATA1 (0x23) +#define SI114X_REG_ALS_IR_DATA0 (0x24) +#define SI114X_REG_ALS_IR_DATA1 (0x25) +#define SI114X_REG_PS1_DATA0 (0x26) +#define SI114X_REG_PS1_DATA1 (0x27) +#define SI114X_REG_PS2_DATA0 (0x28) +#define SI114X_REG_PS2_DATA1 (0x29) +#define SI114X_REG_PS3_DATA0 (0x2A) +#define SI114X_REG_PS3_DATA1 (0x2B) +#define SI114X_REG_UV_INDEX0 (0x2C) +#define SI114X_REG_UV_INDEX1 (0x2D) +#define SI114X_REG_PARAM_RD (0x2E) +#define SI114X_REG_CHIP_STAT (0x30) +/** @} */ + +/** + * @name Si114x response register error codes + * @{ + */ +#define SI114X_NO_ERROR (0x00) +#define SI114X_INVALID_SETTING (0x80) +#define SI114X_PS1_ADC_OVERFLOW (0x88) +#define SI114X_PS2_ADC_OVERFLOW (0x89) +#define SI114X_PS3_ADC_OVERFLOW (0x8A) +#define SI114X_ALS_VIS_ADC_OVERFLOW (0x8C) +#define SI114X_ALS_IR_ADC_OVERFLOW (0x8D) +#define SI114X_UV_ADC_OVERFLOW (0x8E) +/** @} */ + +/** + * @name Si114x parameters RAM + * + * @note These parameter can be accessed indirectly using PARAM_QUERY or + * PARAM_SET commands. + * @{ + */ +#define SI114X_I2C_ADDR (0x00) +#define SI114X_PARAM_CHLIST (0x01) +#define SI114X_PARAM_CHLIST_ENUV (0x80) +#define SI114X_PARAM_CHLIST_ENAUX (0x40) +#define SI114X_PARAM_CHLIST_ENALSIR (0x20) +#define SI114X_PARAM_CHLIST_ENALSVIS (0x10) +#define SI114X_PARAM_CHLIST_ENPS1 (0x01) +#define SI114X_PARAM_CHLIST_ENPS2 (0x02) +#define SI114X_PARAM_CHLIST_ENPS3 (0x04) +#define SI114X_PARAM_PSLED12SEL (0x02) +#define SI114X_PARAM_PSLED12SEL_PS2NONE (0x00) +#define SI114X_PARAM_PSLED12SEL_PS2LED1 (0x10) +#define SI114X_PARAM_PSLED12SEL_PS2LED2 (0x20) +#define SI114X_PARAM_PSLED12SEL_PS2LED3 (0x40) +#define SI114X_PARAM_PSLED12SEL_PS1NONE (0x00) +#define SI114X_PARAM_PSLED12SEL_PS1LED1 (0x01) +#define SI114X_PARAM_PSLED12SEL_PS1LED2 (0x02) +#define SI114X_PARAM_PSLED12SEL_PS1LED3 (0x04) +#define SI114X_PARAM_PSLED3SEL (0x03) +#define SI114X_PARAM_PSENCODE (0x05) +#define SI114X_PARAM_ALSENCODE (0x06) +#define SI114X_PARAM_PS1ADCMUX (0x07) +#define SI114X_PARAM_PS2ADCMUX (0x08) +#define SI114X_PARAM_PS3ADCMUX (0x09) +#define SI114X_PARAM_PSADCOUNTER (0x0A) +#define SI114X_PARAM_PSADCGAIN (0x0B) +#define SI114X_PARAM_PSADCMISC (0x0C) +#define SI114X_PARAM_PSADCMISC_RANGE (0x20) +#define SI114X_PARAM_PSADCMISC_PSMODE (0x04) +#define SI114X_PARAM_ALSIRADCMUX (0x0E) +#define SI114X_PARAM_AUXADCMUX (0x0F) +#define SI114X_PARAM_ALSVISADCOUNTER (0x10) +#define SI114X_PARAM_ALSVISADCGAIN (0x11) +#define SI114X_PARAM_ALSVISADCMISC (0x12) +#define SI114X_PARAM_ALSVISADCMISC_VISRANGE (0x20) +#define SI114X_PARAM_ALSIRADCOUNTER (0x1D) +#define SI114X_PARAM_ALSIRADCGAIN (0x1E) +#define SI114X_PARAM_ALSIRADCMISC (0x1F) +#define SI114X_PARAM_ALSIRADCMISC_RANGE (0x20) +#define SI114X_PARAM_ADCMUX_SMALLIR (0x00) +#define SI114X_PARAM_ADCMUX_LARGEIR (0x03) +/** @} */ + +/** + * @name Si114x constants + * @{ + */ +#define SI1145_ID (0x45) +#define SI1146_ID (0x46) +#define SI1147_ID (0x47) +#define SI114X_STARTUP_TIME (25000UL) /* 25ms */ +#define SI114X_WAIT_10MS (10000UL) /* 10ms */ +#define SI114X_INIT_VALUE (0x17) +#define SI114X_UCOEF0_DEFAULT (0x29) +#define SI114X_UCOEF1_DEFAULT (0x89) +#define SI114X_UCOEF2_DEFAULT (0x02) +#define SI114X_UCOEF3_DEFAULT (0x00) +#define SI114X_ADC_REC_CLK (0x70) /* 511 ADC Clock */ +/** @} */ + +/** + * @name Si114x register bits + * @{ + */ +#define SI114X_EN_UV (0x80) +#define SI114X_EN_AUX (0x40) +#define SI114X_EN_ALS_IR (0x20) +#define SI114X_EN_ALS_VIS (0x10) + +#define SI114X_EN_PS3_IE (0x10) +#define SI114X_EN_PS2_IE (0x08) +#define SI114X_EN_PS1_IE (0x04) +#define SI114X_EN_ALS_IE (0x01) + +#define SI114X_INTCFG_INTOE (0x01) +#define SI114X_INTCFG_INTMODE (0x02) + +#define SI114X_PS3_ALIGN (0x40) +#define SI114X_PS2_ALIGN (0x20) +#define SI114X_PS1_ALIGN (0x10) +#define SI114X_ALS_IR_ALIGN (0x20) +#define SI114X_ALS_VIS_ALIGN (0x10) +#define SI114X_PS_RANGE (0x20) +#define SI114X_PS_ADC_MODE (0x04) +#define SI114X_VIS_RANGE (0x20) +#define SI114X_IR_RANGE (0x20) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* SI114X_INTERNALS_H */ +/** @} */ diff --git a/drivers/si114x/include/si114x_params.h b/drivers/si114x/include/si114x_params.h new file mode 100644 index 0000000000..d261613b10 --- /dev/null +++ b/drivers/si114x/include/si114x_params.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016-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_si114x + * + * @{ + * @file + * @brief Default configuration for SI114x + * + * @author Alexandre Abadie + */ + +#ifndef SI114X_PARAMS_H +#define SI114X_PARAMS_H + +#include "board.h" +#include "si114x.h" +#include "saul_reg.h" +#include "si114x_internals.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Set default configuration parameters for the Si114x + * @{ + */ +#ifndef SI114X_PARAM_I2C_DEV +#define SI114X_PARAM_I2C_DEV I2C_DEV(1) +#endif + +#ifndef SI114X_PARAMS +#define SI114X_PARAMS { .i2c_dev = SI114X_PARAM_I2C_DEV, \ + .led_current = SI114X_PS_LED1 } +#endif +#ifndef SI114X_SAUL_INFO +#define SI114X_SAUL_INFO { .name = "si114x" } +#endif +/**@}*/ + +/** + * @brief Configure Si114x + */ +static const si114x_params_t si114x_params[] = +{ + SI114X_PARAMS +}; + +/** + * @brief Allocate and configure entries to the SAUL registry + */ +saul_reg_t si114x_saul_reg_info[] = +{ + SI114X_SAUL_INFO +}; + +#ifdef __cplusplus +} +#endif + +#endif /* SI114X_PARAMS_H */ +/** @} */ diff --git a/drivers/si114x/si114x.c b/drivers/si114x/si114x.c new file mode 100644 index 0000000000..4a65f82b73 --- /dev/null +++ b/drivers/si114x/si114x.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2016-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_si114x + * @{ + * + * @file + * @brief Device driver implementation for the Si114x proximity/UV/Ambient + * light sensor with I2C interface. + * + * @author Alexandre Abadie + * Bas Stottelaar + * + * @} + */ + +#include +#include +#include + +#include "xtimer.h" + +#include "periph/i2c.h" + +#include "si114x.h" +#include "si114x_internals.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define DEV_I2C (dev->params.i2c_dev) + +/* Internal function prototypes */ +static void _reset(si114x_t *dev); +static void _initialize(si114x_t *dev); +static void _set_param(si114x_t *dev, uint8_t param, uint8_t value); + +/*---------------------------------------------------------------------------* + * Si114x Core API * + *---------------------------------------------------------------------------*/ + +int8_t si114x_init(si114x_t *dev, const si114x_params_t *params) +{ + dev->params = *params; + + /* wait before sensor is ready */ + xtimer_usleep(SI114X_STARTUP_TIME); + + /* initialize I2C interface */ + if (i2c_init_master(DEV_I2C, I2C_SPEED_NORMAL)) { + DEBUG("[Error] I2C device not enabled\n"); + return -SI114X_ERR_I2C; + } + + /* acquire exclusive access */ + i2c_acquire(DEV_I2C); + + /* check sensor ID */ + char checkid = 0; + i2c_read_reg(DEV_I2C, SI114X_ADDR, SI114X_REG_PART_ID, &checkid); + if ((checkid != SI1145_ID) && (checkid != SI1146_ID) && (checkid != SI1147_ID)) { + DEBUG("[Error] The given i2c is not enabled.\n"); + i2c_release(DEV_I2C); + return -SI114X_ERR_NODEV; + } + + /* reset sensor */ + _reset(dev); + + /* initialize internals registers */ + _initialize(dev); + + /* release I2C device */ + i2c_release(DEV_I2C); + + return SI114X_OK; +} + +uint16_t si114x_read_uv(si114x_t *dev) +{ + /* acquire exclusive access */ + i2c_acquire(DEV_I2C); + + uint8_t buffer[2]; + i2c_read_regs(DEV_I2C, SI114X_ADDR, + SI114X_REG_UV_INDEX0, &buffer, 2); + + /* release I2C device */ + i2c_release(DEV_I2C); + + return (uint16_t)(((buffer[1] << 8) | buffer[0]) / 100); +} + +uint16_t si114x_read_ir(si114x_t *dev) +{ + /* acquire exclusive access */ + i2c_acquire(DEV_I2C); + + uint8_t buffer[2]; + i2c_read_regs(DEV_I2C, SI114X_ADDR, + SI114X_REG_ALS_IR_DATA0, &buffer, 2); + + /* release I2C device */ + i2c_release(DEV_I2C); + + return (uint16_t)((buffer[1] << 8) | buffer[0]); +} + +uint16_t si114x_read_visible(si114x_t *dev) +{ + /* acquire exclusive access */ + i2c_acquire(DEV_I2C); + + uint8_t buffer[2]; + i2c_read_regs(DEV_I2C, SI114X_ADDR, + SI114X_REG_ALS_VIS_DATA0, &buffer, 2); + + /* release I2C device */ + i2c_release(DEV_I2C); + + return (uint16_t)((buffer[1] << 8) | buffer[0]); +} + +uint16_t si114x_read_distance(si114x_t *dev) +{ + /* acquire exclusive access */ + i2c_acquire(DEV_I2C); + + uint8_t buffer[2]; + i2c_read_regs(DEV_I2C, SI114X_ADDR, + SI114X_REG_PS1_DATA0, &buffer, 2); + + /* release I2C device */ + i2c_release(DEV_I2C); + + return (uint16_t)((buffer[1] << 8) | buffer[0]); +} + +uint8_t si114x_read_response(si114x_t *dev) +{ + /* acquire exclusive access */ + i2c_acquire(DEV_I2C); + + uint8_t buffer[1]; + i2c_read_regs(DEV_I2C, SI114X_ADDR, + SI114X_REG_RESPONSE, &buffer, 1); + + /* release I2C device */ + i2c_release(DEV_I2C); + + return buffer[0]; +} + +/*------------------------------------------------------------------------------------*/ +/* Internal functions */ +/*------------------------------------------------------------------------------------*/ + +void _reset(si114x_t *dev) +{ + DEBUG("Resetting sensor.\n"); + + /* write configuration values */ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_MEAS_RATE0, 0); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_MEAS_RATE1, 0); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_IRQ_ENABLE, 0); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_IRQ_MODE1, 0); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_IRQ_MODE2, 0); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_INT_CFG, 0); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_IRQ_STATUS, 0xFF); + + /* perform RESET command */ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_COMMAND, SI114X_RESET); + xtimer_usleep(SI114X_WAIT_10MS); + + /* write HW_KEY for proper operation */ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_HW_KEY, SI114X_INIT_VALUE); + xtimer_usleep(SI114X_WAIT_10MS); +} + + +void _initialize(si114x_t *dev) +{ + DEBUG("Initializing sensor.\n"); + + /* set default UV measurement coefs */ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_UCOEF0, SI114X_UCOEF0_DEFAULT); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_UCOEF1, SI114X_UCOEF1_DEFAULT); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_UCOEF2, SI114X_UCOEF2_DEFAULT); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_UCOEF3, SI114X_UCOEF3_DEFAULT); + + /* enable measures */ + _set_param(dev, SI114X_PARAM_CHLIST, + SI114X_PARAM_CHLIST_ENUV | SI114X_PARAM_CHLIST_ENALSIR | + SI114X_PARAM_CHLIST_ENALSVIS | SI114X_PARAM_CHLIST_ENPS1); + + /* enable interrupt on every sample */ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_INT_CFG, SI114X_INTCFG_INTOE); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_IRQ_ENABLE, SI114X_EN_ALS_IE | SI114X_EN_PS1_IE); + + /* active LED current */ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_PS_LED21, dev->params.led_current); + + _set_param(dev, SI114X_PARAM_PS1ADCMUX, SI114X_PARAM_ADCMUX_LARGEIR); + + /* proximity sensor uses LED1 */ + _set_param(dev, SI114X_PARAM_PSLED12SEL, SI114X_PARAM_PSLED12SEL_PS1LED1); + + /* ADC gain */ + _set_param(dev, SI114X_PARAM_PSADCGAIN, 0); + _set_param(dev, SI114X_PARAM_PSADCOUNTER, SI114X_ADC_REC_CLK); + + /* proximity range */ + _set_param(dev, SI114X_PARAM_PSADCMISC, + SI114X_PARAM_PSADCMISC_RANGE | SI114X_PARAM_PSADCMISC_PSMODE); + _set_param(dev, SI114X_PARAM_ALSIRADCMUX, SI114X_PARAM_ADCMUX_SMALLIR); + + /* clocks configuration */ + _set_param(dev, SI114X_PARAM_ALSIRADCGAIN, 0); + _set_param(dev, SI114X_PARAM_ALSIRADCOUNTER, SI114X_ADC_REC_CLK); + + /* high range mode */ + _set_param(dev, SI114X_PARAM_ALSIRADCMISC, SI114X_PARAM_ALSIRADCMISC_RANGE); + + /* clocks config */ + _set_param(dev, SI114X_PARAM_ALSVISADCGAIN, 0); + _set_param(dev, SI114X_PARAM_ALSVISADCOUNTER, SI114X_ADC_REC_CLK); + + _set_param(dev, SI114X_PARAM_ALSVISADCMISC, + SI114X_PARAM_ALSVISADCMISC_VISRANGE); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_MEAS_RATE0, 0xFF); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_MEAS_RATE1, 0x00); + + /* auto-run */ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_COMMAND, SI114X_PS_ALS_AUTO); +} + +void _set_param(si114x_t *dev, uint8_t param, uint8_t value) +{ + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_PARAM_WR, value); + i2c_write_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_COMMAND, param | SI114X_PARAM_SET); + + uint8_t ret; + i2c_read_reg(DEV_I2C, SI114X_ADDR, + SI114X_REG_PARAM_RD, &ret); +} diff --git a/drivers/si114x/si114x_saul.c b/drivers/si114x/si114x_saul.c new file mode 100644 index 0000000000..96f48c5eaf --- /dev/null +++ b/drivers/si114x/si114x_saul.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016-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_si114x + * @{ + * + * @file + * @brief SAUL adaption for Si114x devices family + * + * @author Alexandre Abadie + * + * @} + */ + +#include + +#include "saul.h" +#include "si114x.h" +#include "xtimer.h" + +static int read_uv(const void *dev, phydat_t *res) +{ + si114x_t *d = (si114x_t *)dev; + + res->val[0] = si114x_read_uv(d); + res->unit = UNIT_NONE; + res->scale = 0; + return 1; +} + +static int read_ir(const void *dev, phydat_t *res) +{ + si114x_t *d = (si114x_t *)dev; + + res->val[0] = si114x_read_ir(d); + res->unit = UNIT_LUX; + res->scale = 0; + return 1; +} + +static int read_visible(const void *dev, phydat_t *res) +{ + si114x_t *d = (si114x_t *)dev; + + res->val[0] = si114x_read_visible(d); + res->unit = UNIT_LUX; + res->scale = 0; + return 1; +} + +static int read_distance(const void *dev, phydat_t *res) +{ + si114x_t *d = (si114x_t *)dev; + + res->val[0] = si114x_read_distance(d); + res->unit = UNIT_M; + res->scale = 0; + return 1; +} + +const saul_driver_t si114x_uv_saul_driver = { + .read = read_uv, + .write = saul_notsup, + .type = SAUL_SENSE_ANY +}; + +const saul_driver_t si114x_ir_saul_driver = { + .read = read_ir, + .write = saul_notsup, + .type = SAUL_SENSE_ANY +}; + +const saul_driver_t si114x_visible_saul_driver = { + .read = read_visible, + .write = saul_notsup, + .type = SAUL_SENSE_ANY +}; + +const saul_driver_t si114x_distance_saul_driver = { + .read = read_distance, + .write = saul_notsup, + .type = SAUL_SENSE_ANY +}; diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 868ed9b21e..4fec53670a 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -93,6 +93,11 @@ PSEUDOMODULES += adc121c PSEUDOMODULES += sx1272 PSEUDOMODULES += sx1276 +# include variants of Si114x drivers as pseudo modules +PSEUDOMODULES += si1145 +PSEUDOMODULES += si1146 +PSEUDOMODULES += si1147 + # include variants of Si70xx drivers as pseudo modules PSEUDOMODULES += si7006 PSEUDOMODULES += si7013