diff --git a/drivers/sensors/CMakeLists.txt b/drivers/sensors/CMakeLists.txt index a7f3e0a4aa9..cf13bc90791 100644 --- a/drivers/sensors/CMakeLists.txt +++ b/drivers/sensors/CMakeLists.txt @@ -60,6 +60,15 @@ if(CONFIG_SENSORS) list(APPEND SRCS adxl362_uorb.c) endif() + if(CONFIG_SENSORS_BH1749NUC) + list(APPEND SRCS bh1749nuc_base.c) + if(CONFIG_SENSORS_BH1749NUC_UORB) + list(APPEND SRCS bh1749nuc_uorb.c) + else() + list(APPEND SRCS bh1749nuc.c) + endif() + endif() + if(CONFIG_SENSORS_DHTXX) list(APPEND SRCS dhtxx.c) endif() diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index fe0560debe8..f6a41ba6762 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -141,6 +141,39 @@ config SENSORS_BH1749NUC ---help--- Enable driver support for the Rohm BH1749NUC color sensor. +if SENSORS_BH1749NUC + +config SENSORS_BH1749NUC_UORB + bool "BH1749NUC UORB Interface" + default n + +if SENSORS_BH1749NUC_UORB + +config SENSORS_BH1749NUC_POLL + bool "Enables polling sensor data" + default n + ---help--- + Enables polling of sensor. + +config SENSORS_BH1749NUC_POLL_INTERVAL + int "Polling interval in microseconds, default 1 sec" + depends on SENSORS_BH1749NUC_POLL + default 1000000 + range 0 4294967295 + ---help--- + The interval until a new sensor measurement will be triggered. + +config SENSORS_BH1749NUC_THREAD_STACKSIZE + int "Worker thread stack size" + depends on SENSORS_BH1749NUC_POLL + default 1024 + ---help--- + The stack size for the worker thread. + +endif #SENSORS_BH1749NUC_UORB + +endif # SENSORS_BH1749NUC + config SENSORS_BH1750FVI bool "Rohm BH1750FVI Ambient Light Sensor support" default n diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index f12c5634798..9e0d5e8881e 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -147,8 +147,13 @@ ifeq ($(CONFIG_ADXL345_I2C),y) endif ifeq ($(CONFIG_SENSORS_BH1749NUC),y) + CSRCS += bh1749nuc_base.c +ifeq ($(CONFIG_SENSORS_BH1749NUC_UORB),y) + CSRCS += bh1749nuc_uorb.c +else CSRCS += bh1749nuc.c endif +endif ifeq ($(CONFIG_SENSORS_BH1750FVI),y) CSRCS += bh1750fvi.c diff --git a/drivers/sensors/bh1749nuc.c b/drivers/sensors/bh1749nuc.c index 8c1a91cad49..8e5940b4daa 100644 --- a/drivers/sensors/bh1749nuc.c +++ b/drivers/sensors/bh1749nuc.c @@ -24,66 +24,7 @@ #include -#include -#include -#include -#include - -#include -#include - -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#define BH1749NUC_I2C_FREQ 400000 - -#define BH1749NUC_MANUFACTID 0xE0 /* Manufact ID */ -#define BH1749NUC_PARTID 0x0D /* Part ID */ - -/* BH1749NUC Registers */ - -#define BH1749NUC_SYSTEM_CONTROL 0x40 -#define BH1749NUC_MODE_CONTROL1 0x41 -#define BH1749NUC_MODE_CONTROL2 0x42 -#define BH1749NUC_RED_DATA_LSB 0x50 -#define BH1749NUC_GREEN_DATA_LSB 0x52 -#define BH1749NUC_BLUE_DATA_LSB 0x54 -#define BH1749NUC_IR_DATA_LSB 0x58 -#define BH1749NUC_GREEN2_DATA_LSB 0x5a -#define BH1749NUC_MANUFACTURER_ID 0x92 - -/* Register SYSTEM_CONTROL */ - -#define BH1749NUC_SYSTEM_CONTROL_SW_RESET (1 << 7) -#define BH1749NUC_SYSTEM_CONTROL_INT_RESET (1 << 6) - -/* Register MODE_CONTROL1 */ - -#define BH1749NUC_MODE_CONTROL1_IR_GAIN_X1 (0x20) -#define BH1749NUC_MODE_CONTROL1_IR_GAIN_X32 (0x60) -#define BH1749NUC_MODE_CONTROL1_RGB_GAIN_X1 (0x08) -#define BH1749NUC_MODE_CONTROL1_RGB_GAIN_X32 (0x18) -#define BH1749NUC_MODE_CONTROL1_MEAS_TIME160MS (0x02) - -/* Register MODE_CONTROL2 */ - -#define BH1749NUC_MODE_CONTROL2_RGBI_EN (1 << 4) - -/**************************************************************************** - * Private Type Definitions - ****************************************************************************/ - -/* Structure for bh1749nuc device */ - -struct bh1749nuc_dev_s -{ - FAR struct i2c_master_s *i2c; /* I2C interface */ - int freq; /* Frequency */ - uint8_t addr; /* I2C address */ -}; +#include "bh1749nuc_base.h" /**************************************************************************** * Private Function Prototypes @@ -120,146 +61,6 @@ static const struct file_operations g_bh1749nucfops = * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: bh1749nuc_getreg8 - * - * Description: - * Read from an 8-bit BH1749NUC register - * - ****************************************************************************/ - -static uint8_t bh1749nuc_getreg8(FAR struct bh1749nuc_dev_s *priv, - uint8_t regaddr) -{ - struct i2c_msg_s msg[2]; - uint8_t regval = 0; - int ret; - - msg[0].frequency = priv->freq; - msg[0].addr = priv->addr; - msg[0].flags = I2C_M_NOSTOP; - msg[0].buffer = ®addr; - msg[0].length = 1; - - msg[1].frequency = priv->freq; - msg[1].addr = priv->addr; - msg[1].flags = I2C_M_READ; - msg[1].buffer = ®val; - msg[1].length = 1; - - ret = I2C_TRANSFER(priv->i2c, msg, 2); - if (ret < 0) - { - snerr("I2C_TRANSFER failed: %d\n", ret); - } - - return regval; -} - -/**************************************************************************** - * Name: bh1749nuc_read16 - * - * Description: - * Read 16-bit register - * - ****************************************************************************/ - -static uint16_t bh1749nuc_read16(FAR struct bh1749nuc_dev_s *priv, - uint8_t regaddr) -{ - struct i2c_msg_s msg[2]; - uint8_t regval[2]; - int ret; - - msg[0].frequency = priv->freq; - msg[0].addr = priv->addr; - msg[0].flags = I2C_M_NOSTOP; - msg[0].buffer = ®addr; - msg[0].length = 1; - - msg[1].frequency = priv->freq; - msg[1].addr = priv->addr; - msg[1].flags = I2C_M_READ; - msg[1].buffer = (uint8_t *)®val; - msg[1].length = 2; - - ret = I2C_TRANSFER(priv->i2c, msg, 2); - if (ret < 0) - { - snerr("I2C_TRANSFER failed: %d\n", ret); - } - - return regval[1] << 8 | regval[0] << 0; -} - -/**************************************************************************** - * Name: bh1749nuc_putreg8 - * - * Description: - * Write to an 8-bit BH1749NUC register - * - ****************************************************************************/ - -static void bh1749nuc_putreg8(FAR struct bh1749nuc_dev_s *priv, - uint8_t regaddr, uint8_t regval) -{ - struct i2c_msg_s msg[2]; - uint8_t txbuffer[2]; - int ret; - - txbuffer[0] = regaddr; - txbuffer[1] = regval; - - msg[0].frequency = priv->freq; - msg[0].addr = priv->addr; - msg[0].flags = 0; - msg[0].buffer = txbuffer; - msg[0].length = 2; - - ret = I2C_TRANSFER(priv->i2c, msg, 1); - if (ret < 0) - { - snerr("I2C_TRANSFER failed: %d\n", ret); - } -} - -/**************************************************************************** - * Name: bh1749nuc_checkid - * - * Description: - * Read and verify the BH1749NUC chip ID - * - ****************************************************************************/ - -static int bh1749nuc_checkid(FAR struct bh1749nuc_dev_s *priv) -{ - uint8_t id; - - /* Read Manufact ID */ - - id = bh1749nuc_getreg8(priv, BH1749NUC_MANUFACTURER_ID); - if (id != BH1749NUC_MANUFACTID) - { - /* Manufact ID is not Correct */ - - snerr("Wrong Manufact ID! %02x\n", id); - return -ENODEV; - } - - /* Read Part ID */ - - id = bh1749nuc_getreg8(priv, BH1749NUC_SYSTEM_CONTROL); - if ((id & 0x3f) != BH1749NUC_PARTID) - { - /* Part ID is not Correct */ - - snerr("Wrong Part ID! %02x\n", id); - return -ENODEV; - } - - return OK; -} - /**************************************************************************** * Name: bh1749nuc_open * diff --git a/drivers/sensors/bh1749nuc_base.c b/drivers/sensors/bh1749nuc_base.c new file mode 100644 index 00000000000..01e86ad8757 --- /dev/null +++ b/drivers/sensors/bh1749nuc_base.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * drivers/sensors/bh1749nuc_base.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "bh1749nuc_base.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bh1749nuc_getreg8 + * + * Description: + * Read from an 8-bit BH1749NUC register + * + ****************************************************************************/ + +uint8_t bh1749nuc_getreg8(FAR struct bh1749nuc_dev_s *priv, uint8_t regaddr) +{ + struct i2c_msg_s msg[2]; + uint8_t regval = 0; + int ret; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].frequency = priv->freq; + msg[1].addr = priv->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = ®val; + msg[1].length = 1; + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } + + return regval; +} + +/**************************************************************************** + * Name: bh1749nuc_read16 + * + * Description: + * Read 16-bit register + * + ****************************************************************************/ + +uint16_t bh1749nuc_read16(FAR struct bh1749nuc_dev_s *priv, uint8_t regaddr) +{ + struct i2c_msg_s msg[2]; + uint8_t regval[2]; + int ret; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = I2C_M_NOSTOP; + msg[0].buffer = ®addr; + msg[0].length = 1; + + msg[1].frequency = priv->freq; + msg[1].addr = priv->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = (uint8_t *)®val; + msg[1].length = 2; + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } + + return regval[1] << 8 | regval[0] << 0; +} + +/**************************************************************************** + * Name: bh1749nuc_putreg8 + * + * Description: + * Write to an 8-bit BH1749NUC register + * + ****************************************************************************/ + +void bh1749nuc_putreg8(FAR struct bh1749nuc_dev_s *priv, + uint8_t regaddr, uint8_t regval) +{ + struct i2c_msg_s msg[2]; + uint8_t txbuffer[2]; + int ret; + + txbuffer[0] = regaddr; + txbuffer[1] = regval; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = 0; + msg[0].buffer = txbuffer; + msg[0].length = 2; + + ret = I2C_TRANSFER(priv->i2c, msg, 1); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } +} + +/**************************************************************************** + * Name: bh1749nuc_checkid + * + * Description: + * Read and verify the BH1749NUC chip ID + * + ****************************************************************************/ + +int bh1749nuc_checkid(FAR struct bh1749nuc_dev_s *priv) +{ + uint8_t id; + + /* Read Manufact ID */ + + id = bh1749nuc_getreg8(priv, BH1749NUC_MANUFACTURER_ID); + if (id != BH1749NUC_MANUFACTID) + { + /* Manufact ID is not Correct */ + + snerr("Wrong Manufact ID! %02x\n", id); + return -ENODEV; + } + + /* Read Part ID */ + + id = bh1749nuc_getreg8(priv, BH1749NUC_SYSTEM_CONTROL); + if ((id & 0x3f) != BH1749NUC_PARTID) + { + /* Part ID is not Correct */ + + snerr("Wrong Part ID! %02x\n", id); + return -ENODEV; + } + + return OK; +} diff --git a/drivers/sensors/bh1749nuc_base.h b/drivers/sensors/bh1749nuc_base.h new file mode 100644 index 00000000000..02925382759 --- /dev/null +++ b/drivers/sensors/bh1749nuc_base.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * drivers/sensors/bh1749nuc_base.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_SENSORS_BH1749NUC_BASE_H +#define __INCLUDE_NUTTX_SENSORS_BH1749NUC_BASE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define BH1749NUC_I2C_FREQ 400000 + +#define BH1749NUC_MANUFACTID 0xE0 /* Manufact ID */ +#define BH1749NUC_PARTID 0x0D /* Part ID */ + +/* BH1749NUC Registers */ + +#define BH1749NUC_SYSTEM_CONTROL 0x40 +#define BH1749NUC_MODE_CONTROL1 0x41 +#define BH1749NUC_MODE_CONTROL2 0x42 +#define BH1749NUC_RED_DATA_LSB 0x50 +#define BH1749NUC_GREEN_DATA_LSB 0x52 +#define BH1749NUC_BLUE_DATA_LSB 0x54 +#define BH1749NUC_IR_DATA_LSB 0x58 +#define BH1749NUC_GREEN2_DATA_LSB 0x5a +#define BH1749NUC_MANUFACTURER_ID 0x92 + +/* Register SYSTEM_CONTROL */ + +#define BH1749NUC_SYSTEM_CONTROL_SW_RESET (1 << 7) +#define BH1749NUC_SYSTEM_CONTROL_INT_RESET (1 << 6) + +/* Register MODE_CONTROL1 */ + +#define BH1749NUC_MODE_CONTROL1_IR_GAIN_X1 (0x20) +#define BH1749NUC_MODE_CONTROL1_IR_GAIN_X32 (0x60) +#define BH1749NUC_MODE_CONTROL1_RGB_GAIN_X1 (0x08) +#define BH1749NUC_MODE_CONTROL1_RGB_GAIN_X32 (0x18) +#define BH1749NUC_MODE_CONTROL1_MEAS_TIME160MS (0x02) + +/* Register MODE_CONTROL2 */ + +#define BH1749NUC_MODE_CONTROL2_RGBI_EN (1 << 4) +#define BH1749NUC_MODE_CONTROL2_VALID (1 << 7) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Structure for bh1749nuc device */ + +struct bh1749nuc_dev_s +{ + FAR struct i2c_master_s *i2c; /* I2C interface */ + int freq; /* Frequency */ + uint8_t addr; /* I2C address */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +uint8_t bh1749nuc_getreg8(FAR struct bh1749nuc_dev_s *priv, uint8_t regaddr); +uint16_t bh1749nuc_read16(FAR struct bh1749nuc_dev_s *priv, uint8_t regaddr); +void bh1749nuc_putreg8(FAR struct bh1749nuc_dev_s *priv, + uint8_t regaddr, uint8_t regval); +int bh1749nuc_checkid(FAR struct bh1749nuc_dev_s *priv); + +#endif /* __INCLUDE_NUTTX_SENSORS_BH1749NUC_BASE_H */ diff --git a/drivers/sensors/bh1749nuc_uorb.c b/drivers/sensors/bh1749nuc_uorb.c new file mode 100644 index 00000000000..a6a53a2c32e --- /dev/null +++ b/drivers/sensors/bh1749nuc_uorb.c @@ -0,0 +1,536 @@ +/**************************************************************************** + * drivers/sensors/bh1749nuc_uorb.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include + +#include + +#include "bh1749nuc_base.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +enum bh1749nuc_idx_e +{ + BH1749NUC_RGB_IDX = 0, + BH1749NUC_IR_IDX, + BH1749NUC_MAX_IDX +}; + +struct bh1749nuc_sensor_dev_s; +struct bh1749nuc_sensor_s +{ + struct sensor_lowerhalf_s lower; + int gain; + FAR struct bh1749nuc_sensor_dev_s *dev; +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + unsigned long interval; + uint64_t last_update; +#endif + bool enabled; +}; + +struct bh1749nuc_sensor_dev_s +{ + struct bh1749nuc_sensor_s priv[BH1749NUC_MAX_IDX]; + struct bh1749nuc_dev_s dev; + float scale_r; + float scale_g; + float scale_b; + float scale_ir; + mutex_t lock; +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + sem_t run; +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int bh1749nuc_activate(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, bool enable); +#ifndef CONFIG_SENSORS_BH1749NUC_POLL +static int bh1749nuc_fetch(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR char *buffer, size_t buflen); +#endif +static int bh1749nuc_set_interval(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR unsigned long *period_us); +static int bh1749nuc_control(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct sensor_ops_s g_bh1749nuc_sensor_ops = +{ + NULL, /* open */ + NULL, /* close */ + bh1749nuc_activate, + bh1749nuc_set_interval, + NULL, /* batch */ +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + NULL, /* fetch */ +#else + bh1749nuc_fetch, +#endif + NULL, /* selftest */ + NULL, /* set_calibvalue */ + NULL, /* calibrate */ + bh1749nuc_control +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bh1749nuc_activate + ****************************************************************************/ + +static int bh1749nuc_activate(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, bool enable) +{ + FAR struct bh1749nuc_sensor_s *priv = NULL; + FAR struct bh1749nuc_dev_s *dev = NULL; + uint8_t val = 0; +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + bool start_thread = false; +#endif + + /* Get dev */ + + priv = (FAR struct bh1749nuc_sensor_s *)lower; + dev = &priv->dev->dev; + + nxmutex_lock(&priv->dev->lock); + + if (enable) + { +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + if (!priv->enabled) + { + start_thread = true; + priv->last_update = sensor_get_timestamp(); + } +#endif + + /* MODE_CONTROL1 */ + + val = (BH1749NUC_MODE_CONTROL1_MEAS_TIME160MS | + BH1749NUC_MODE_CONTROL1_IR_GAIN_X1 | + BH1749NUC_MODE_CONTROL1_RGB_GAIN_X1); + bh1749nuc_putreg8(dev, BH1749NUC_MODE_CONTROL1, val); + + /* MODE_CONTROL2 */ + + val = BH1749NUC_MODE_CONTROL2_RGBI_EN; + bh1749nuc_putreg8(dev, BH1749NUC_MODE_CONTROL2, val); + } + else + { + /* Stop sampling */ + + val = 0; + bh1749nuc_putreg8(dev, BH1749NUC_MODE_CONTROL2, val); + } + + priv->enabled = enable; + +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + if (start_thread) + { + /* Wake up the thread */ + + nxsem_post(&priv->dev->run); + } +#endif + + nxmutex_unlock(&priv->dev->lock); + + return OK; +} + +#ifndef CONFIG_SENSORS_BH1749NUC_POLL +/**************************************************************************** + * Name: bh1749nuc_fetch + ****************************************************************************/ + +static int bh1749nuc_fetch(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR char *buffer, size_t buflen) +{ + FAR struct bh1749nuc_sensor_s *priv = NULL; + FAR struct bh1749nuc_dev_s *dev = NULL; + struct sensor_rgb rgb_data; + struct sensor_ir ir_data; + uint16_t tmp = 0; + uint64_t now = sensor_get_timestamp(); + int ret = 0; + + /* Get dev */ + + priv = (FAR struct bh1749nuc_sensor_s *)lower; + dev = &priv->dev->dev; + + nxmutex_lock(&priv->dev->lock); + + if (!priv->enabled) + { + ret = -EACCES; + goto errout; + } + + /* Wait for data */ + + while (!(bh1749nuc_getreg8(dev, BH1749NUC_MODE_CONTROL2) & + BH1749NUC_MODE_CONTROL2_VALID)); + + if (lower->type == SENSOR_TYPE_RGB) + { + if (buflen != sizeof(rgb_data)) + { + ret = -EINVAL; + goto errout; + } + + rgb_data.timestamp = now; + tmp = bh1749nuc_read16(dev, BH1749NUC_RED_DATA_LSB); + rgb_data.r = (tmp * dev->scale_r); + tmp = bh1749nuc_read16(dev, BH1749NUC_GREEN_DATA_LSB); + rgb_data.g = (tmp * dev->scale_g); + tmp = bh1749nuc_read16(dev, BH1749NUC_BLUE_DATA_LSB); + rgb_data.b = (tmp * dev->scale_b); + + memcpy(buffer, &rgb_data, sizeof(rgb_data)); + ret = sizeof(rgb_data); + } + else if (lower->type == SENSOR_TYPE_IR) + { + if (buflen != sizeof(ir_data)) + { + ret = -EINVAL; + goto errout; + } + + ir_data.timestamp = now; + tmp = bh1749nuc_read16(dev, BH1749NUC_IR_DATA_LSB); + ir_data.ir = (tmp * dev->scale_ir); + + memcpy(buffer, &ir_data, sizeof(ir_data)); + ret = sizeof(ir_data); + } + +errout: + nxmutex_unlock(&priv->dev->lock); + return ret; +} +#endif + +/**************************************************************************** + * Name: bh1749nuc_cotrol + ****************************************************************************/ + +static int bh1749nuc_control(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, int cmd, + unsigned long arg) +{ + FAR struct bh1749nuc_sensor_s *priv = NULL; + int ret = OK; + + priv = (FAR struct bh1749nuc_sensor_s *)lower; + UNUSED(priv); + + switch (cmd) + { + default: + { + snerr("ERROR: Unrecognized cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + } + + return ret; +} + +/**************************************************************************** + * Name: bh1749nuc_set_interval + ****************************************************************************/ + +static int bh1749nuc_set_interval(FAR struct sensor_lowerhalf_s *lower, + FAR struct file *filep, + FAR unsigned long *interval) +{ +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + FAR struct bh1749nuc_sensor_s *priv = NULL; + + priv = (FAR struct bh1749nuc_sensor_s *)lower; + + priv->interval = *interval; +#endif + + return OK; +} + +#ifdef CONFIG_SENSORS_BH1749NUC_POLL +/**************************************************************************** + * Name: bh1749nuc_thread + * + * Description: Thread for performing interval measurement cycle and data + * read. + * + * Parameter: + * argc - Number opf arguments + * argv - Pointer to argument list + * + ****************************************************************************/ + +static int bh1749nuc_thread(int argc, FAR char **argv) +{ + FAR struct bh1749nuc_sensor_dev_s *dev = + (FAR struct bh1749nuc_sensor_dev_s *)((uintptr_t)strtoul(argv[1], NULL, + 16)); + FAR struct bh1749nuc_sensor_s *rgb = &dev->priv[BH1749NUC_RGB_IDX]; + FAR struct bh1749nuc_sensor_s *ir = &dev->priv[BH1749NUC_IR_IDX]; + struct sensor_rgb rgb_data; + struct sensor_ir ir_data; + uint64_t min_interval; + uint16_t tmp = 0; + uint64_t now = sensor_get_timestamp(); + int ret = 0; + + while (true) + { + if ((!rgb->enabled) && (!ir->enabled)) + { + /* Waiting to be woken up */ + + ret = nxsem_wait(&dev->run); + if (ret < 0) + { + continue; + } + } + + /* Wait for data */ + + while (!(bh1749nuc_getreg8(&dev->dev, BH1749NUC_MODE_CONTROL2) & + BH1749NUC_MODE_CONTROL2_VALID)); + + /* Get timestamp */ + + now = sensor_get_timestamp(); + + if (rgb->enabled) + { + rgb_data.timestamp = now; + tmp = bh1749nuc_read16(&dev->dev, BH1749NUC_RED_DATA_LSB); + rgb_data.r = (tmp * dev->scale_r); + tmp = bh1749nuc_read16(&dev->dev, BH1749NUC_GREEN_DATA_LSB); + rgb_data.g = (tmp * dev->scale_g); + tmp = bh1749nuc_read16(&dev->dev, BH1749NUC_BLUE_DATA_LSB); + rgb_data.b = (tmp * dev->scale_b); + + rgb->lower.push_event(rgb->lower.priv, + &rgb_data, sizeof(rgb_data)); + } + + if (ir->enabled) + { + ir_data.timestamp = now; + tmp = bh1749nuc_read16(&dev->dev, BH1749NUC_IR_DATA_LSB); + ir_data.ir = (tmp * dev->scale_ir); + + ir->lower.push_event(ir->lower.priv, + &ir_data, sizeof(ir_data)); + } + + /* Sleeping thread before fetching the next sensor data */ + + min_interval = MIN(rgb->interval, ir->interval); + nxsig_usleep(min_interval); + } + + return OK; +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bh1749nuc_register_uorb + * + * Description: + * Register the BH1749NUC uorb device as 'devpath' + * + * Input Parameters: + * devno - The user specifies device number, from 0. + * config - device configuration + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int bh1749nuc_register_uorb(int devno, FAR struct bh1749nuc_config_s *config) +{ + FAR struct bh1749nuc_sensor_dev_s *dev = NULL; + FAR struct bh1749nuc_sensor_s *tmp = NULL; + int ret = OK; +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + FAR char *argv[2]; + char arg1[32]; +#endif + + /* Without config info, we can't do anything. */ + + if (config == NULL) + { + return -EINVAL; + } + + /* Initialize the device structure. */ + + dev = kmm_malloc(sizeof(struct bh1749nuc_sensor_dev_s)); + if (dev == NULL) + { + snerr("ERROR: Failed to allocate bh1749nuc device instance\n"); + return -ENOMEM; + } + + memset(dev, 0, sizeof(struct bh1749nuc_sensor_dev_s)); + nxmutex_init(&dev->lock); +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + nxsem_init(&dev->run, 0, 0); +#endif + + /* Configure dev */ + + dev->dev.i2c = config->i2c; + dev->dev.addr = config->addr; + dev->dev.freq = BH1749NUC_I2C_FREQ; + + /* Check Device ID */ + + ret = bh1749nuc_checkid(&dev->dev); + if (ret < 0) + { + snerr("Failed to register driver: %d\n", ret); + return ret; + } + + /* Return data in lux unit for RGB and IR */ + + dev->scale_r = (20.0f / 71.0f) * (1e-6 / 1.46e-7); + dev->scale_g = (20.0f / 99.0f) * (1e-6 / 1.46e-7); + dev->scale_b = (20.0f / 70.0f) * (1e-6 / 1.46e-7); + dev->scale_ir = (20.0f / 25.0f) * (1e-6 / 1.46e-7); + + /* Register sensor */ + + tmp = &dev->priv[BH1749NUC_RGB_IDX]; + tmp->lower.type = SENSOR_TYPE_RGB; + tmp->lower.ops = &g_bh1749nuc_sensor_ops; + tmp->dev = dev; + tmp->gain = 1; +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + tmp->enabled = false; + tmp->interval = CONFIG_SENSORS_BH1749NUC_POLL_INTERVAL; +#endif + + ret = sensor_register(&tmp->lower, devno); + if (ret < 0) + { + goto rgb_err; + } + + /* Register sensor */ + + tmp = &dev->priv[BH1749NUC_IR_IDX]; + tmp->lower.type = SENSOR_TYPE_IR; + tmp->lower.ops = &g_bh1749nuc_sensor_ops; + tmp->dev = dev; + tmp->gain = 1; +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + tmp->enabled = false; + tmp->interval = CONFIG_SENSORS_BH1749NUC_POLL_INTERVAL; +#endif + + ret = sensor_register(&tmp->lower, devno); + if (ret < 0) + { + goto ir_err; + } + +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + /* Create thread for polling sensor data */ + + snprintf(arg1, 16, "%p", dev); + argv[0] = arg1; + argv[1] = NULL; + + ret = kthread_create("bh1749nuc_thread", SCHED_PRIORITY_DEFAULT, + CONFIG_SENSORS_BH1749NUC_THREAD_STACKSIZE, + bh1749nuc_thread, + argv); + if (ret < 0) + { + goto thr_err; + } +#endif + + return ret; + +#ifdef CONFIG_SENSORS_BH1749NUC_POLL + thr_err: +#endif + sensor_unregister(&dev->priv[BH1749NUC_IR_IDX].lower, devno); +ir_err: + sensor_unregister(&dev->priv[BH1749NUC_RGB_IDX].lower, devno); +rgb_err: + kmm_free(dev); + return ret; +} diff --git a/include/nuttx/sensors/bh1749nuc.h b/include/nuttx/sensors/bh1749nuc.h index 33f559bade8..9892ad885a6 100644 --- a/include/nuttx/sensors/bh1749nuc.h +++ b/include/nuttx/sensors/bh1749nuc.h @@ -46,6 +46,12 @@ struct bh1749nuc_data_s uint16_t green2; }; +struct bh1749nuc_config_s +{ + FAR struct i2c_master_s *i2c; + uint8_t addr; +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -75,8 +81,13 @@ extern "C" * ****************************************************************************/ +#ifndef CONFIG_SENSORS_BH1749NUC_UORB int bh1749nuc_register(FAR const char *devpath, FAR struct i2c_master_s *i2c, uint8_t addr); +#else +int bh1749nuc_register_uorb(int devno, + FAR struct bh1749nuc_config_s *config); +#endif #undef EXTERN #ifdef __cplusplus