robertalexa2000 commented on code in PR #7466: URL: https://github.com/apache/incubator-nuttx/pull/7466#discussion_r1008922556
########## drivers/sensors/ltr308.c: ########## @@ -0,0 +1,1000 @@ +/**************************************************************************** + * drivers/sensors/ltr308.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. + * + ****************************************************************************/ + +/* Character driver for the LTR-308ALS-01 Lite-On ambient light sensor */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <debug.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/fs/fs.h> +#include <nuttx/i2c/i2c_master.h> +#include <nuttx/sensors/ltr308.h> + +#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_LTR308) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LTR308_ADDR 0x53 +#define LTR308_FREQ CONFIG_LTR308_I2C_FREQUENCY +#define DEVID 0xB1 + +#define LTR308_CTRL 0x00 +#define LTR308_MEAS_RATE 0x04 +#define LTR308_ALS_GAIN 0x05 +#define LTR308_PART_ID 0x06 +#define LTR308_STATUS 0x07 +#define LTR308_DATA_0 0x0D +#define LTR308_DATA_1 0x0E +#define LTR308_DATA_2 0x0F +#define LTR308_INTERRUPT 0x19 +#define LTR308_INTR_PERS 0x1A +#define LTR308_THRES_UP_0 0x21 +#define LTR308_THRES_UP_1 0x22 +#define LTR308_THRES_UP_2 0x23 +#define LTR308_THRES_LOW_0 0x24 +#define LTR308_THRES_LOW_1 0x25 +#define LTR308_THRES_LOW_2 0x26 + +#define BYTE_TO_BITS 8 + +/**************************************************************************** + * Private Type Definitions + ****************************************************************************/ + +struct ltr308_dev_s +{ + FAR struct i2c_master_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ + int freq; /* I2C bus frequency */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + bool unlinked; /* True, driver has been unlinked */ + int16_t crefs; /* Number of open references */ +#endif + sem_t devsem; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int ltr308_open(FAR struct file *filep); +static int ltr308_close(FAR struct file *filep); +#endif +static ssize_t ltr308_read(FAR struct file *filep, FAR char *buffer, + size_t len); +static ssize_t ltr308_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS +static int ltr308_unlink(FAR struct inode *inode); +#endif + +/**************************************************************************** + * Private Data +****************************************************************************/ + +static const struct file_operations g_ltr308fops = +{ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + .open = ltr308_open, + .close = ltr308_close, +#endif + .read = ltr308_read, + .ioctl = ltr308_ioctl, +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + .unlink = ltr308_unlink, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: ltr308_set_reg8 + * + * Description: + * Write to an 8-bit LTR308 register + * + ****************************************************************************/ + +static int ltr308_set_reg8(FAR struct ltr308_dev_s *priv, uint8_t regaddr, + uint8_t regval) +{ + struct i2c_msg_s msg; + uint8_t txbuffer[2]; + int ret; + + txbuffer[0] = regaddr; + txbuffer[1] = regval; + + msg.frequency = priv->freq; + msg.addr = priv->addr; + msg.flags = 0; + msg.buffer = txbuffer; + msg.length = 2; + + ret = I2C_TRANSFER(priv->i2c, &msg, 1); + if (ret < 0) + { + snerr("I2C_TRANSFER failed\n"); + } + + return ret; +} + +/**************************************************************************** + * Name: ltr308_get_reg8 + * + * Description: + * Read from an 8-bit LTR308 register + * + ****************************************************************************/ + +static int ltr308_get_reg8(FAR struct ltr308_dev_s *priv, uint8_t regaddr, + FAR uint8_t *regval) +{ + struct i2c_msg_s msg[2]; + int ret; + + msg[0].frequency = priv->freq; + msg[0].addr = priv->addr; + msg[0].flags = 0; + 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 = regval; + msg[1].length = 1; + + ret = I2C_TRANSFER(priv->i2c, msg, 2); + if (ret < 0) + { + snerr("I2C_TRANSFER failed: %d\n", ret); + } + + return ret; +} + +/**************************************************************************** + * Name: ltr308_set_reg24 + * + * Description: + * Write to 3 8-bit LTR308 registers + * + ****************************************************************************/ + +static int ltr308_set_reg24(FAR struct ltr308_dev_s *priv, uint8_t regaddr, + uint32_t val) +{ + int i, ret; + + for (i = 0; i < 3; i++, regaddr++) + { + ret = ltr308_set_reg8(priv, regaddr, val); + if (ret < 0) + { + return ret; + } + + val >>= BYTE_TO_BITS; + } + + return ret; +} + +/**************************************************************************** + * Name: ltr308_get_reg24 + * + * Description: + * Read from 3 8-bit LTR308 registers + * + ****************************************************************************/ + +static int ltr308_get_reg24(FAR struct ltr308_dev_s *priv, uint8_t regaddr, + FAR uint32_t *val) +{ + int i, ret; + + *val = 0; + for (i = 0; i < 3; i++, regaddr++) + { + ret = ltr308_get_reg8(priv, regaddr, ((uint8_t *)val) + i); + if (ret < 0) + { + return ret; + } + } + + return ret; +} + +/**************************************************************************** + * Name: ltr308_set_ctrl + * + * Description: + * Power up, shut down or reset LTR308 + * + ****************************************************************************/ + +static inline int ltr308_set_ctrl(FAR struct ltr308_dev_s *priv, + bool reset, bool enable) +{ + return ltr308_set_reg8(priv, LTR308_CTRL, (reset << 4) | (enable << 1)); +} + +/**************************************************************************** + * Name: ltr308_get_ctrl + * + ****************************************************************************/ + +static int ltr308_get_ctrl(FAR struct ltr308_dev_s *priv, FAR bool *reset, + FAR bool *enable) +{ + uint8_t ctrl; + int ret; + + ret = ltr308_get_reg8(priv, LTR308_CTRL, &ctrl); + if (ret < 0) + { + return ret; + } + + *reset = ctrl >> 4; + *enable = ctrl & 0x02; + + return ret; +} + +/**************************************************************************** + * Name: ltr308_set_measrate + * + * Description: + * Set the integration time and measurement rate of LTR308 + * Integration time is the measurement time for each ALS cycle + * Measurement rate is the interval between DATA_REGISTERS update + * Measurement rate must be set to be equal or greater than integration time + * + ****************************************************************************/ + +static int ltr308_set_measrate(FAR struct ltr308_dev_s *priv, + uint8_t integration_time, + uint8_t measurement_rate) +{ + uint8_t measurement = 0x00; + + /* Sanity checks */ + + if (integration_time >= 5) + { + integration_time = 0; + } + if (measurement_rate >= 6 || measurement_rate == 4) + { + measurement_rate = 0; + } + + measurement |= integration_time << 4; + measurement |= measurement_rate; + + return ltr308_set_reg8(priv, LTR308_MEAS_RATE, measurement); +} + +/**************************************************************************** + * Name: ltr308_get_measrate + * + ****************************************************************************/ + +static int ltr308_get_measrate(FAR struct ltr308_dev_s *priv, + FAR uint8_t *integration_time, + FAR uint8_t *measurement_rate) +{ + uint8_t measurement; + int ret; + + ret = ltr308_get_reg8(priv, LTR308_MEAS_RATE, &measurement); + if (ret < 0) + { + return ret; + } + + *integration_time = (measurement & 0x70) >> 4; + *measurement_rate = measurement & 0x07; + + return ret; +} + +/**************************************************************************** + * Name: ltr308_set_gain + * + * Description: + * Set the gain of LTR308 + * + ****************************************************************************/ + +static int ltr308_set_gain(FAR struct ltr308_dev_s *priv, uint8_t gain) +{ + /* sanity check */ + + if (gain >= 5) + { + gain = 0; + } + + return ltr308_set_reg8(priv, LTR308_ALS_GAIN, gain); +} + +/**************************************************************************** + * Name: ltr308_get_gain + * + ****************************************************************************/ + +static inline int ltr308_get_gain(FAR struct ltr308_dev_s *priv, + FAR uint8_t *gain) +{ + return ltr308_get_reg8(priv, LTR308_ALS_GAIN, gain); +} + +/**************************************************************************** + * Name: ltr308_checkid + * + * Description: + * Read and verify the LTR308 chip ID + * + ****************************************************************************/ + +static int ltr308_checkid(FAR struct ltr308_dev_s *priv) +{ + uint8_t devid; + int ret; + + /* Read device ID */ + + ret = ltr308_get_reg8(priv, LTR308_PART_ID, &devid); + if (ret < 0) + { + return ret; + } + sninfo("devid: 0x%02x\n", devid); + + if (devid != (uint8_t) DEVID) + return -ENODEV; + + return ret; +} + +/**************************************************************************** + * Name: ltr308_get_status + * + * Description: + * Get the status information of LTR308 + * + ****************************************************************************/ + +static int ltr308_get_status(FAR struct ltr308_dev_s *priv, + FAR bool *power_on, + FAR bool *interrupt_pending, + FAR bool *data_pending) +{ + uint8_t status; + uint8_t ret; + + ret = ltr308_get_reg8(priv, LTR308_STATUS, &status); + if (ret < 0) + { + return ret; + } + + *power_on = status & 0x20; + *interrupt_pending = status & 0x10; + *data_pending = status & 0x08; + + return ret; +} + +/**************************************************************************** + * Name: ltr308_get_data + * + * Description: + * Get the ALS channel data of LTR308 + * + ****************************************************************************/ + +static inline int ltr308_get_data(FAR struct ltr308_dev_s *priv, + FAR uint32_t *data) +{ + return ltr308_get_reg24(priv, LTR308_DATA_0, data); +} + +/**************************************************************************** + * Name: ltr308_set_intrmode + * + * Description: + * Set up interrupt operations + * + ****************************************************************************/ + +static inline int ltr308_set_intrmode(FAR struct ltr308_dev_s *priv, + bool on) +{ + return ltr308_set_reg8(priv, LTR308_INTERRUPT, 0x10 | (on << 2)); +} + +/**************************************************************************** + * Name: ltr308_get_intrmode + * + ****************************************************************************/ + +static int ltr308_get_intrmode(FAR struct ltr308_dev_s *priv, + FAR bool *on) +{ + uint8_t interrupt_control; + int ret; + + ret = ltr308_get_reg8(priv, LTR308_INTERRUPT, &interrupt_control); + if (ret < 0) + { + return ret; + } + + *on = interrupt_control & 0x04; + + return ret; +} + +/**************************************************************************** + * Name: ltr308_set_intrpers + * + * Description: + * Set up interrupt persistance (controls the N number of times the + * measurement data is outside the range defined by upper and lower + * threshold) + * + ****************************************************************************/ + +static int ltr308_set_intrpers(FAR struct ltr308_dev_s *priv, + uint8_t intr_pers) +{ + /* Sanity check */ + + if (intr_pers >= 16) + { + intr_pers = 0; + } + + return ltr308_set_reg8(priv, LTR308_INTR_PERS, intr_pers << 4); +} + +/**************************************************************************** + * Name: ltr308_get_intrpers + * + ****************************************************************************/ + +static int ltr308_get_intrpers(FAR struct ltr308_dev_s *priv, + FAR uint8_t *intr_pers) +{ + int ret; + + ret = ltr308_get_reg8(priv, LTR308_INTR_PERS, intr_pers); + if (ret < 0) + { + return ret; + } + + *intr_pers >>= 4; + + return ret; +} + +/**************************************************************************** + * Name: ltr308_set_threshold + * + * Description: + * Set the upper and lower limits of the threshold + * + ****************************************************************************/ + +static inline int ltr308_set_threshold(FAR struct ltr308_dev_s *priv, + uint32_t upper_limit, + uint32_t lower_limit) +{ + return ltr308_set_reg24(priv, LTR308_THRES_UP_0, upper_limit) | + ltr308_set_reg24(priv, LTR308_THRES_LOW_0, lower_limit); +} + +/**************************************************************************** + * Name: ltr308_get_threshold + * + ****************************************************************************/ + +static inline int ltr308_get_threshold(FAR struct ltr308_dev_s *priv, + FAR uint32_t *upper_limit, + FAR uint32_t *lower_limit) +{ + return ltr308_get_reg24(priv, LTR308_THRES_UP_0, upper_limit) | + ltr308_get_reg24(priv, LTR308_THRES_LOW_0, lower_limit); +} + +/**************************************************************************** + * Name: ltr308_get_lux + * Convert raw data to lux + * + ****************************************************************************/ + +static int ltr308_get_lux(FAR struct ltr308_dev_s *priv, uint8_t gain, Review Comment: Hmm, I think we won't be able to to signal -ENODATA back to the user if the function is void. And we need to do so if the sensor in saturated -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org