From 1ca44cf072a14689fee55479cb6bc6ca83a275c2 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Tue, 7 Mar 2017 11:31:39 +0100 Subject: [PATCH] drivers/vcnl40x0: initial implementation --- drivers/Makefile.dep | 5 + drivers/Makefile.include | 4 + drivers/include/saul.h | 1 + drivers/include/vcnl40x0.h | 149 +++++++++++++++ drivers/vcnl40x0/Makefile | 1 + drivers/vcnl40x0/include/vcnl40x0_internals.h | 139 ++++++++++++++ drivers/vcnl40x0/include/vcnl40x0_params.h | 83 +++++++++ drivers/vcnl40x0/vcnl40x0.c | 172 ++++++++++++++++++ drivers/vcnl40x0/vcnl40x0_saul.c | 59 ++++++ 9 files changed, 613 insertions(+) create mode 100644 drivers/include/vcnl40x0.h create mode 100644 drivers/vcnl40x0/Makefile create mode 100644 drivers/vcnl40x0/include/vcnl40x0_internals.h create mode 100644 drivers/vcnl40x0/include/vcnl40x0_params.h create mode 100644 drivers/vcnl40x0/vcnl40x0.c create mode 100644 drivers/vcnl40x0/vcnl40x0_saul.c diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index e5a0c9991d..6a3de6c93d 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -452,6 +452,11 @@ ifneq (,$(filter uart_half_duplex,$(USEMODULE))) USEMODULE += xtimer endif +ifneq (,$(filter vcnl40%0,$(USEMODULE))) + USEMODULE += vcnl40x0 + FEATURES_REQUIRED += periph_i2c +endif + ifneq (,$(filter veml6070,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c endif diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 83c994ef37..19bb780f39 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -246,6 +246,10 @@ ifneq (,$(filter uart_half_duplex,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/uart_half_duplex/include endif +ifneq (,$(filter vcnl40x0,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/vcnl40x0/include +endif + ifneq (,$(filter veml6070,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/veml6070/include endif diff --git a/drivers/include/saul.h b/drivers/include/saul.h index c678d6b19f..75b12ca573 100644 --- a/drivers/include/saul.h +++ b/drivers/include/saul.h @@ -97,6 +97,7 @@ enum { SAUL_SENSE_CO2 = 0x8f, /**< sensor: CO2 Gas */ SAUL_SENSE_TVOC = 0x90, /**< sensor: TVOC Gas */ SAUL_SENSE_OCCUP = 0x91, /**< sensor: occupancy */ + SAUL_SENSE_PROXIMITY= 0x92, /**< sensor: proximity */ SAUL_CLASS_ANY = 0xff /**< any device - wildcard */ /* extend this list as needed... */ }; diff --git a/drivers/include/vcnl40x0.h b/drivers/include/vcnl40x0.h new file mode 100644 index 0000000000..43006a8d34 --- /dev/null +++ b/drivers/include/vcnl40x0.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2017 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_vcnl40x0 VCNL4010/VCNL4020/VCNL4040 Proximity and Ambient Light Sensors + * @ingroup drivers_sensors + * @brief Device driver interface for the VCNL40X0 Proximity and Ambient Light Sensors. + * @{ + * + * @file + * @brief Device driver interface for the VCNL40X0 sensors family. + * + * @note VCNL4010, VCNL4020 and VCNL4040 are supported. + * + * @author Alexandre Abadie + */ + +#ifndef VCNL40X0_H +#define VCNL40X0_H + +#include "saul.h" +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Proximity measure rate + */ +enum { + VCNL40X0_PROXIMITY_RATE_2 = 0, /**< 1.95 measurements/s (default) */ + VCNL40X0_PROXIMITY_RATE_4, /**< 3.90625 measurements/s */ + VCNL40X0_PROXIMITY_RATE_8, /**< 7.8125 measurements/s */ + VCNL40X0_PROXIMITY_RATE_16, /**< 16.625 measurements/s */ + VCNL40X0_PROXIMITY_RATE_31, /**< 31.25 measurements/s */ + VCNL40X0_PROXIMITY_RATE_62, /**< 62.5 measurements/s */ + VCNL40X0_PROXIMITY_RATE_125, /**< 125 measurements/s */ + VCNL40X0_PROXIMITY_RATE_250, /**< 250 measurements/s */ +}; + +/** + * @brief Ambient light measurement rate + */ +enum { + VCNL40X0_AMBIENT_RATE_1 = 0, /**< 1 sample/s */ + VCNL40X0_AMBIENT_RATE_2, /**< 2 sample/s (default) */ + VCNL40X0_AMBIENT_RATE_3, /**< 3 sample/s */ + VCNL40X0_AMBIENT_RATE_4, /**< 4 sample/s */ + VCNL40X0_AMBIENT_RATE_5, /**< 5 sample/s */ + VCNL40X0_AMBIENT_RATE_6, /**< 6 sample/s */ + VCNL40X0_AMBIENT_RATE_8, /**< 8 sample/s */ + VCNL40X0_AMBIENT_RATE_10, /**< 10 sample/s */ +}; + +/** + * @brief Ambient light number of conversions during one measurement cycle + * + * Number of conversions = 2^decimal value + */ +enum { + VCNL40X0_AMBIENT_AVERAGE_1 = 0, /**< Decimal value 1 */ + VCNL40X0_AMBIENT_AVERAGE_2, /**< Decimal value 2 */ + VCNL40X0_AMBIENT_AVERAGE_4, /**< Decimal value 4 */ + VCNL40X0_AMBIENT_AVERAGE_8, /**< Decimal value 8 */ + VCNL40X0_AMBIENT_AVERAGE_16, /**< Decimal value 16 */ + VCNL40X0_AMBIENT_AVERAGE_32, /**< Decimal value 32 (default) */ + VCNL40X0_AMBIENT_AVERAGE_64, /**< Decimal value 64 */ + VCNL40X0_AMBIENT_AVERAGE_128, /**< Decimal value 128 */ +}; + +/** + * @brief Status and error return codes + */ +enum { + VCNL40X0_OK = 0, /**< Everything was fine */ + VCNL40X0_ERR_I2C, /**< Error initializing the I2C bus */ + VCNL40X0_ERR_NODEV /**< Error wrong device */ +}; + +/** + * @brief Device initialization parameters + */ +typedef struct { + i2c_t i2c_dev; /**< I2C device which is used */ + uint8_t i2c_addr; /**< Address on I2C bus */ + uint8_t led_current; /**< LED current */ + uint8_t proximity_rate; /**< Proximity rate */ + uint8_t ambient_rate; /**< Ambient light rate */ + uint8_t ambient_avg; /**< Ambient light conversion average */ +} vcnl40x0_params_t; + +/** + * @brief Device descriptor for the VCNL40X0 sensor + */ +typedef struct { + vcnl40x0_params_t params; /**< Device parameters */ +} vcnl40x0_t; + +/** + * @brief Initialize the given VCNL40X0 device + * + * @param[out] dev Initialized device descriptor of VCNL40X0 device + * @param[in] params The parameters for the VCNL40X0 device + * + * @return VCNL40X0_OK on success + * @return -VCNL40X0_ERR_I2C if given I2C is not enabled in board config + * @return -VCNL40X0_ERR_NODEV if not a vcnl40X0 device + */ +int vcnl40x0_init(vcnl40x0_t *dev, const vcnl40x0_params_t *params); + +/** + * @brief Read proximity value from the vcnl40X0 device + * + * @param[in] dev Device descriptor of VCNL40X0 device to read from + * + * @return Proximity in counts + */ +uint16_t vcnl40x0_read_proximity(const vcnl40x0_t *dev); + +/** + * @brief Read ambient light value from the vcnl40X0 device + * + * @param[in] dev Device descriptor of VCNL40X0 device to read from + * + * @return Ambient light in counts + */ +uint16_t vcnl40x0_read_ambient_light(const vcnl40x0_t *dev); + +/** + * @brief Read illuminance value from the vcnl40X0 device + * + * @param[in] dev Device descriptor of VCNL40X0 device to read from + * + * @return Illuminance in lux + */ +uint16_t vcnl40x0_read_illuminance(const vcnl40x0_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* VCNL40X0_H */ +/** @} */ diff --git a/drivers/vcnl40x0/Makefile b/drivers/vcnl40x0/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/vcnl40x0/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/vcnl40x0/include/vcnl40x0_internals.h b/drivers/vcnl40x0/include/vcnl40x0_internals.h new file mode 100644 index 0000000000..50851eefcb --- /dev/null +++ b/drivers/vcnl40x0/include/vcnl40x0_internals.h @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2017 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_vcnl40x0 + * @{ + * + * @file + * @brief Internal addresses, registers, constants for the VCNL40X0 devices. + * + * @author Alexandre Abadie + * @} + */ + +#ifndef VCNL40X0_INTERNALS_H +#define VCNL40X0_INTERNALS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief VCNL40X0 I2C address + */ +#define VCNL40X0_ADDR (0x13) + +/** + * @brief VCNL40X0 product ID + */ +#define VCNL40X0_PRODUCT_ID (0x20) + +/** + * @name VCNL40X0 registers + * @{ + */ +#define VCNL40X0_REG_COMMAND (0x80) +#define VCNL40X0_REG_PRODUCT_ID (0x81) +#define VCNL40X0_REG_PROXIMITY_RATE (0x82) +#define VCNL40X0_REG_PROXIMITY_CURRENT (0x83) +#define VCNL40X0_REG_AMBIENT_PARAMETER (0x84) +#define VCNL40X0_REG_AMBIENT_VALUE (0x85) +#define VCNL40X0_REG_PROXIMITY_VALUE (0x87) +#define VCNL40X0_REG_INTERRUPT_CONTROL (0x89) +#define VCNL40X0_REG_INTERRUPT_LOW_THRES (0x8a) +#define VCNL40X0_REG_HIGH_THRES (0x8c) +#define VCNL40X0_REG_INTERRUPT_STATUS (0x8e) +#define VCNL40X0_REG_PROX_TIMING (0xf9) +#define VCNL40X0_REG_AMBIENT_IR_LIGHT_LEVEL (0x90) /* should not be used */ +/** @} */ + +/** + * @name VCNL40X0 command register constants + * @{ + */ +#define VCNL40X0_COMMAND_ALL_DISABLE (0x00) +#define VCNL40X0_COMMAND_SELFTIMED_MODE_ENABLE (0x01) +#define VCNL40X0_COMMAND_PROX_ENABLE (0x02) +#define VCNL40X0_COMMAND_AMBI_ENABLE (0x04) +#define VCNL40X0_COMMAND_PROX_ON_DEMAND (0x08) +#define VCNL40X0_COMMAND_AMBI_ON_DEMAND (0x10) +#define VCNL40X0_COMMAND_MASK_PROX_DATA_READY (0x20) +#define VCNL40X0_COMMAND_MASK_AMBI_DATA_READY (0x40) +#define VCNL40X0_COMMAND_MASK_LOCK (0x80) +/** @} */ + +/** + * @name VCNL40X0 product ID register constants + * @{ + */ +#define VCNL40X0_PRODUCT_MASK_REVISION_ID (0x0f) +#define VCNL40X0_PRODUCT_MASK_PRODUCT_ID (0xf0) +/** @} */ + +/** + * @name VCNL40X0 proximity rate register constants + * @{ + */ +#define VCNL40X0_PROXIMITY_MASK_MEASUREMENT_RATE (0x07) +#define VCNL40X0_PROXIMITY_MASK_LED_CURRENT (0x3f) +#define VCNL40X0_PROXIMITY_MASK_FUSE_PROG_ID (0xc0) +/** @} */ + +/** + * @name VCNL40X0 ambient light parameter register constants + * @{ + */ +#define VCNL40X0_AMBIENT_MASK_PARA_AVERAGE (0x07) +#define VCNL40X0_AMBIENT_PARA_AUTO_OFFSET_ENABLE (0x08) +#define VCNL40X0_AMBIENT_MASK_PARA_AUTO_OFFSET (0x08) +#define VCNL40X0_AMBIENT_MASK_PARA_MEAS_RATE (0x70) +#define VCNL40X0_AMBIENT_PARA_CONT_CONV_ENABLE (0x80) +#define VCNL40X0_AMBIENT_MASK_PARA_CONT_CONV (0x80) +/** @} */ + +/** + * @name VCNL40X0 interrupt control register constants + * @{ + */ +#define VCNL40X0_INTERRUPT_THRES_SEL_PROX (0x00) +#define VCNL40X0_INTERRUPT_THRES_SEL_ALS (0x01) +#define VCNL40X0_INTERRUPT_THRES_ENABLE (0x02) +#define VCNL40X0_INTERRUPT_ALS_READY_ENABLE (0x04) +#define VCNL40X0_INTERRUPT_PROX_READY_ENABLE (0x08) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_1 (0x00) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_2 (0x20) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_4 (0x40) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_8 (0x60) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_16 (0x80) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_32 (0xa0) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_64 (0xc0) +#define VCNL40X0_INTERRUPT_COUNT_EXCEED_128 (0xe0) +#define VCNL40X0_INTERRUPT_MASK_COUNT_EXCEED (0xe0) +/** @} */ + +/** + * @name VCNL40X0 interrupt status register constants + * @{ + */ +#define VCNL40X0_INTERRUPT_STATUS_THRES_HI (0x01) +#define VCNL40X0_INTERRUPT_STATUS_THRES_LO (0x02) +#define VCNL40X0_INTERRUPT_STATUS_ALS_READY (0x04) +#define VCNL40X0_INTERRUPT_STATUS_PROX_READY (0x08) +#define VCNL40X0_INTERRUPT_MASK_STATUS_THRES_HI (0x01) +#define VCNL40X0_INTERRUPT_MASK_THRES_LO (0x02) +#define VCNL40X0_INTERRUPT_MASK_ALS_READY (0x04) +#define VCNL40X0_INTERRUPT_MASK_PROX_READY (0x08) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* VCNL40X0_INTERNALS_H */ +/** @} */ diff --git a/drivers/vcnl40x0/include/vcnl40x0_params.h b/drivers/vcnl40x0/include/vcnl40x0_params.h new file mode 100644 index 0000000000..c04c900385 --- /dev/null +++ b/drivers/vcnl40x0/include/vcnl40x0_params.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 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_vcnl40x0 + * + * @{ + * @file + * @brief Default configuration for VCNL40X0 devices + * + * @author Alexandre Abadie + */ + +#ifndef VCNL40X0_PARAMS_H +#define VCNL40X0_PARAMS_H + +#include "board.h" +#include "vcnl40x0.h" +#include "vcnl40x0_internals.h" +#include "saul_reg.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Default configuration parameters for the VCNL40X0 + * @{ + */ +#ifndef VCNL40X0_PARAM_I2C_DEV +#define VCNL40X0_PARAM_I2C_DEV I2C_DEV(0) +#endif +#ifndef VCNL40X0_PARAM_I2C_ADDR +#define VCNL40X0_PARAM_I2C_ADDR (VCNL40X0_ADDR) +#endif +#ifndef VCNL40X0_PARAM_LED_CURRENT +#define VCNL40X0_PARAM_LED_CURRENT (2U) +#endif +#ifndef VCNL40X0_PARAM_PROXIMITY_RATE +#define VCNL40X0_PARAM_PROXIMITY_RATE (VCNL40X0_PROXIMITY_RATE_2) +#endif +#ifndef VCNL40X0_PARAM_AMBIENT_AVG +#define VCNL40X0_PARAM_AMBIENT_AVG (VCNL40X0_AMBIENT_AVERAGE_32) +#endif +#ifndef VCNL40X0_PARAM_AMBIENT_RATE +#define VCNL40X0_PARAM_AMBIENT_RATE (VCNL40X0_AMBIENT_RATE_2) +#endif + +#define VCNL40X0_PARAMS { .i2c_dev = VCNL40X0_PARAM_I2C_DEV, \ + .i2c_addr = VCNL40X0_PARAM_I2C_ADDR, \ + .led_current = VCNL40X0_PARAM_LED_CURRENT, \ + .proximity_rate = VCNL40X0_PARAM_PROXIMITY_RATE, \ + .ambient_avg = VCNL40X0_PARAM_AMBIENT_AVG, \ + .ambient_rate = VCNL40X0_PARAM_AMBIENT_RATE } +/**@}*/ + +/** + * @brief Configure VCNL40X0 + */ +static const vcnl40x0_params_t vcnl40x0_params[] = +{ + VCNL40X0_PARAMS, +}; + +/** + * @brief Configure SAUL registry entries + */ +static const saul_reg_info_t vcnl40x0_saul_reg_info[] = +{ + { .name = "vcnl40x0" } +}; + +#ifdef __cplusplus +} +#endif + +#endif /* VCNL40X0_PARAMS_H */ +/** @} */ diff --git a/drivers/vcnl40x0/vcnl40x0.c b/drivers/vcnl40x0/vcnl40x0.c new file mode 100644 index 0000000000..06abfdc8d8 --- /dev/null +++ b/drivers/vcnl40x0/vcnl40x0.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2017 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_vcnl40x0 + * @{ + * + * @file + * @brief Device driver implementation for VCNL40X0 Proximity and Ambient Light devices. + * + * @author Alexandre Abadie + * + * @} + */ + +#include "vcnl40x0.h" +#include "vcnl40x0_internals.h" +#include "vcnl40x0_params.h" +#include "periph/i2c.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#define DEV_I2C (dev->params.i2c_dev) +#define DEV_ADDR (dev->params.i2c_addr) + +/* Internal functions */ +static int _set_command_reg(const vcnl40x0_t *dev, uint8_t reg) +{ + if (i2c_write_reg(DEV_I2C, DEV_ADDR, VCNL40X0_REG_COMMAND, reg, 0) != 0) { + return -1; + } + + return 0; +} + +static int _get_command_reg(const vcnl40x0_t *dev, uint8_t *reg) +{ + if (i2c_read_reg(DEV_I2C, DEV_ADDR, VCNL40X0_REG_COMMAND, reg, 0) != 0) { + return -1; + } + + return 0; +} + +/*---------------------------------------------------------------------------* + * VCNL40X0 Core API * + *---------------------------------------------------------------------------*/ + +int vcnl40x0_init(vcnl40x0_t *dev, const vcnl40x0_params_t *params) +{ + dev->params = *params; + + /* Acquire exclusive access */ + i2c_acquire(DEV_I2C); + + /* Check sensor ID */ + uint8_t checkid; + i2c_read_reg(DEV_I2C, DEV_ADDR, VCNL40X0_REG_PRODUCT_ID, + &checkid, 0); + if ((checkid & VCNL40X0_PRODUCT_MASK_PRODUCT_ID) != VCNL40X0_PRODUCT_ID) { + DEBUG("[vcnl40x0] Error: wrong device ID '0x%02x', expected '0x%02x'\n", + checkid, VCNL40X0_PRODUCT_ID); + i2c_release(DEV_I2C); + return -VCNL40X0_ERR_NODEV; + } + + /* LED current cannot be above 20 */ + if (dev->params.led_current > 20) { + dev->params.led_current = 20; + } + + if (i2c_write_reg(DEV_I2C, DEV_ADDR, VCNL40X0_REG_PROXIMITY_CURRENT, + dev->params.led_current, 0) != 0) { + DEBUG("[vcnl40x0] Error: failed to set proximity current\n"); + i2c_release(DEV_I2C); + return -VCNL40X0_ERR_I2C; + } + + if (_set_command_reg(dev, VCNL40X0_COMMAND_ALL_DISABLE) < 0) { + DEBUG("[vcnl40x0] Error: failed to set disable all commands\n"); + i2c_release(DEV_I2C); + return -VCNL40X0_ERR_I2C; + } + + if (i2c_write_reg(DEV_I2C, DEV_ADDR, VCNL40X0_REG_PROXIMITY_RATE, + dev->params.proximity_rate, 0) != 0) { + DEBUG("[vcnl40x0] Error: failed to set proximity rate\n"); + i2c_release(DEV_I2C); + return -VCNL40X0_ERR_I2C; + } + + if (i2c_write_reg(DEV_I2C, DEV_ADDR, VCNL40X0_REG_AMBIENT_PARAMETER, + dev->params.ambient_rate | + VCNL40X0_AMBIENT_PARA_AUTO_OFFSET_ENABLE | + dev->params.ambient_avg, 0) != 0) { + DEBUG("[vcnl40x0] Error: failed to set ambient light rate\n"); + i2c_release(DEV_I2C); + return -VCNL40X0_ERR_I2C; + } + + /* Release I2C device */ + i2c_release(DEV_I2C); + + DEBUG("[vcnl40x0] info: vcnl40x0 sensor initialized with success\n"); + + return VCNL40X0_OK; +} + +uint16_t vcnl40x0_read_proximity(const vcnl40x0_t *dev) +{ + i2c_acquire(DEV_I2C); + + _set_command_reg(dev, + VCNL40X0_COMMAND_PROX_ENABLE | + VCNL40X0_COMMAND_PROX_ON_DEMAND); + uint16_t cnt = 0xffff; + while (cnt--) { + uint8_t reg; + _get_command_reg(dev, ®); + if (reg & VCNL40X0_COMMAND_MASK_PROX_DATA_READY) { + uint8_t prox_buf[2]; + i2c_read_regs(DEV_I2C, DEV_ADDR, VCNL40X0_REG_PROXIMITY_VALUE, + &prox_buf, 2, 0); + uint16_t res = (uint16_t)((prox_buf[0] << 8) | prox_buf[1]); + DEBUG("[vcnl40x0] Proximity read: %i\n", res); + i2c_release(DEV_I2C); + return res; + } + } + + i2c_release(DEV_I2C); + return 0; +} + +uint16_t vcnl40x0_read_ambient_light(const vcnl40x0_t *dev) +{ + i2c_acquire(DEV_I2C); + + _set_command_reg(dev, + VCNL40X0_COMMAND_AMBI_ENABLE | + VCNL40X0_COMMAND_AMBI_ON_DEMAND); + + uint16_t cnt = 0xffff; + while (cnt--) { + uint8_t reg; + _get_command_reg(dev, ®); + if (reg & VCNL40X0_COMMAND_MASK_AMBI_DATA_READY) { + uint8_t ambient_buf[2]; + i2c_read_regs(DEV_I2C, DEV_ADDR, VCNL40X0_REG_AMBIENT_VALUE, + &ambient_buf, 2, 0); + uint16_t res = (uint16_t)((ambient_buf[0] << 8) | ambient_buf[1]); + DEBUG("[vcnl40x0] Ambient light read: %i\n", res); + i2c_release(DEV_I2C); + return res; + } + } + + i2c_release(DEV_I2C); + + return 0; +} + +uint16_t vcnl40x0_read_illuminance(const vcnl40x0_t *dev) +{ + return vcnl40x0_read_ambient_light(dev) >> 2; +} diff --git a/drivers/vcnl40x0/vcnl40x0_saul.c b/drivers/vcnl40x0/vcnl40x0_saul.c new file mode 100644 index 0000000000..b2bc4df217 --- /dev/null +++ b/drivers/vcnl40x0/vcnl40x0_saul.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2017 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_vcnl40x0 + * @{ + * + * @file + * @brief SAUL adaption for VCNL40X0 devices + * + * @author Hauke Petersen + * @author Alexandre Abadie + * + * @} + */ + +#include + +#include "saul.h" +#include "vcnl40x0.h" +#include "vcnl40x0_params.h" +#include "xtimer.h" + +static int read_proximity(const void *dev, phydat_t *res) +{ + const vcnl40x0_t *d = (vcnl40x0_t *)dev; + + res->val[0] = (int16_t)vcnl40x0_read_proximity(d); + res->unit = UNIT_CTS; + res->scale = 0; + return 1; +} + +static int read_illuminance(const void *dev, phydat_t *res) +{ + const vcnl40x0_t *d = (vcnl40x0_t *)dev; + + res->val[0] = (int16_t)vcnl40x0_read_illuminance(d); + res->unit = UNIT_LUX; + res->scale = 0; + return 1; +} + +const saul_driver_t vcnl40x0_proximity_saul_driver = { + .read = read_proximity, + .write = saul_notsup, + .type = SAUL_SENSE_PROXIMITY +}; + +const saul_driver_t vcnl40x0_illuminance_saul_driver = { + .read = read_illuminance, + .write = saul_notsup, + .type = SAUL_SENSE_LIGHT +};