mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 05:42:05 +08:00
0dccc8ba21
debug.h is a NuttX-specific, non-POSIX header. Placing it in the top-level include/ directory creates naming conflicts with external projects that define their own debug.h. This commit moves the canonical header to include/nuttx/debug.h, following the NuttX convention for non-POSIX/non-standard headers, and updates all in-tree references. A backward-compatibility shim is left at include/debug.h that emits a deprecation #warning and re-includes <nuttx/debug.h>, allowing out-of-tree code to continue building while migrating. Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
813 lines
23 KiB
C
813 lines
23 KiB
C
/****************************************************************************
|
|
* drivers/analog/ads1115.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* 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 <nuttx/config.h>
|
|
#include <nuttx/nuttx.h>
|
|
#include <nuttx/signal.h>
|
|
|
|
#include <assert.h>
|
|
#include <nuttx/debug.h>
|
|
#include <endian.h>
|
|
#include <errno.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <nuttx/analog/adc.h>
|
|
#include <nuttx/analog/ads1115.h>
|
|
#include <nuttx/analog/ioctl.h>
|
|
#include <nuttx/arch.h>
|
|
#include <nuttx/i2c/i2c_master.h>
|
|
|
|
/****************************************************************************
|
|
* Preprocessor definitions
|
|
****************************************************************************/
|
|
|
|
#define ADS1115_NUM_CHANNELS 8
|
|
|
|
#define ADS1115_OS_SHIFT (1 << 15)
|
|
#define ADS1115_MUX_SHIFT (12)
|
|
#define ADS1115_MUX_MASK (7 << ADS1115_MUX_SHIFT)
|
|
#define ADS1115_PGA_SHIFT (9)
|
|
#define ADS1115_PGA_MASK (7 << ADS1115_PGA_SHIFT)
|
|
#define ADS1115_MODE_MASK (1 << 8)
|
|
#define ADS1115_DR_SHIFT (5)
|
|
#define ADS1115_DR_MASK (7 << ADS1115_DR_SHIFT)
|
|
#define ADS1115_COMP_MODE_MASK (1 << 4)
|
|
#define ADS1115_COMP_POL_MASK (1 << 3)
|
|
#define ADS1115_COMP_LAT_MASK (1 << 2)
|
|
#define ADS1115_COMP_QUE_SHIFT (0)
|
|
#define ADS1115_COMP_QUE_MASK (3 << ADS1115_COMP_QUE_SHIFT)
|
|
|
|
/* Helper macros for checking modes */
|
|
|
|
#define ADS1115_ONESHOT_MODE(priv) \
|
|
(((priv->cmdbyte & ADS1115_MODE_MASK) == ADS1115_MODE_MASK))
|
|
#define ADS1115_CHANNEL_BITS(am_channel) (am_channel << ADS1115_MUX_SHIFT)
|
|
|
|
/* The conversion time is based on the data rate */
|
|
|
|
#define ADS1115_CONVERSION_TIME (1000000 / (1 << (CONFIG_ADC_ADS1115_DR + 3)))
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
struct ads1115_dev_s
|
|
{
|
|
FAR struct i2c_master_s *i2c;
|
|
FAR const struct adc_callback_s *cb;
|
|
uint8_t addr;
|
|
|
|
/* Current configuration of ADC. */
|
|
|
|
uint16_t cmdbyte;
|
|
};
|
|
|
|
enum ads1115_registers_e
|
|
{
|
|
ADS1115_CONVERSION_REGISTER = 0x00,
|
|
ADS1115_CONFIG_REGISTER = 0x01,
|
|
ADS1115_LO_THRESH_REGISTER = 0x02,
|
|
ADS1115_HI_THRESH_REGISTER = 0x03,
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Function Prototypes
|
|
****************************************************************************/
|
|
|
|
static int ads1115_bind(FAR struct adc_dev_s *dev,
|
|
FAR const struct adc_callback_s *callback);
|
|
static void ads1115_reset(FAR struct adc_dev_s *dev);
|
|
static int ads1115_setup(FAR struct adc_dev_s *dev);
|
|
static void ads1115_shutdown(FAR struct adc_dev_s *dev);
|
|
static void ads1115_rxint(FAR struct adc_dev_s *dev, bool enable);
|
|
static int ads1115_ioctl(FAR struct adc_dev_s *dev, int cmd,
|
|
unsigned long arg);
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
static const struct adc_ops_s g_ads1115ops =
|
|
{
|
|
.ao_bind = ads1115_bind,
|
|
.ao_reset = ads1115_reset,
|
|
.ao_setup = ads1115_setup,
|
|
.ao_shutdown = ads1115_shutdown,
|
|
.ao_rxint = ads1115_rxint,
|
|
.ao_ioctl = ads1115_ioctl,
|
|
};
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_write_register
|
|
*
|
|
* Description:
|
|
* Writes a value to a register in the ADS1115.
|
|
*
|
|
* Input Parameters:
|
|
* priv - An ADS1115 device structure
|
|
* reg - The register to write to.
|
|
* value - The value to write to the register, in big endian.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int ads1115_write_register(FAR struct ads1115_dev_s *priv,
|
|
enum ads1115_registers_e reg,
|
|
uint16_t value)
|
|
{
|
|
int ret = OK;
|
|
struct i2c_msg_s i2cmsg;
|
|
uint8_t cmd[3];
|
|
|
|
DEBUGASSERT(priv != NULL);
|
|
|
|
/* Setup write cmd */
|
|
|
|
cmd[0] = (uint8_t)reg;
|
|
cmd[1] = (uint8_t)(value & 0xff);
|
|
cmd[2] = (uint8_t)((value >> 8) & 0xff);
|
|
|
|
/* Write the register */
|
|
|
|
i2cmsg.frequency = CONFIG_ADC_ADS1115_I2C_FREQUENCY;
|
|
i2cmsg.addr = priv->addr;
|
|
i2cmsg.flags = 0;
|
|
i2cmsg.buffer = cmd;
|
|
i2cmsg.length = 3;
|
|
|
|
ret = I2C_TRANSFER(priv->i2c, &i2cmsg, 1);
|
|
if (ret < 0)
|
|
{
|
|
aerr("ADS1115 I2C transfer failed: %d\n", ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_read_register
|
|
*
|
|
* Description:
|
|
* Reads a value from a register in the ADS1115 in big endian.
|
|
*
|
|
* Input Parameters:
|
|
* priv - An ADS1115 device structure
|
|
* reg - The register to read from.
|
|
* buf - A pointer to a buffer to store the value read from the register.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int ads1115_read_register(FAR struct ads1115_dev_s *priv, uint8_t reg,
|
|
uint16_t *buf)
|
|
{
|
|
int ret = OK;
|
|
struct i2c_msg_s i2cmsg[2];
|
|
|
|
DEBUGASSERT(priv != NULL);
|
|
DEBUGASSERT(buf != NULL);
|
|
|
|
/* Write the register into the address pointer register. */
|
|
|
|
i2cmsg[0].frequency = CONFIG_ADC_ADS1115_I2C_FREQUENCY;
|
|
i2cmsg[0].addr = priv->addr;
|
|
i2cmsg[0].flags = 0;
|
|
i2cmsg[0].buffer = (FAR uint8_t *)(®);
|
|
i2cmsg[0].length = sizeof(reg);
|
|
|
|
/* Read from the register. */
|
|
|
|
i2cmsg[1].frequency = CONFIG_ADC_ADS1115_I2C_FREQUENCY;
|
|
i2cmsg[1].addr = priv->addr;
|
|
i2cmsg[1].flags = I2C_M_READ;
|
|
i2cmsg[1].buffer = (FAR uint8_t *)(buf);
|
|
i2cmsg[1].length = sizeof(*buf);
|
|
|
|
ret = I2C_TRANSFER(priv->i2c, i2cmsg, 2);
|
|
if (ret < 0)
|
|
{
|
|
aerr("ADS1115 I2C transfer failed: %d\n", ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: cmdbyte_init
|
|
*
|
|
* Description:
|
|
* Initializes the command byte with the default settings, and writes to the
|
|
* high and low threshold registers.
|
|
*
|
|
* Input Parameters:
|
|
* priv - An ADS1115 device structure
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int cmdbyte_init(FAR struct ads1115_dev_s *priv)
|
|
{
|
|
int ret = OK;
|
|
|
|
/* Set the default channel. */
|
|
|
|
priv->cmdbyte = CONFIG_ADC_ADS1115_CHANNEL << ADS1115_MUX_SHIFT;
|
|
|
|
/* Set the default pga setting. */
|
|
|
|
priv->cmdbyte |= CONFIG_ADC_ADS1115_PGA << ADS1115_PGA_SHIFT;
|
|
|
|
/* Set the default mode. */
|
|
|
|
#ifndef CONFIG_ADC_ADS1115_CONTINOUS
|
|
priv->cmdbyte |= ADS1115_MODE_MASK;
|
|
#endif
|
|
|
|
/* Set the default data rate. */
|
|
|
|
priv->cmdbyte |= CONFIG_ADC_ADS1115_DR << ADS1115_DR_SHIFT;
|
|
|
|
/* Set the default comparator mode. */
|
|
|
|
#ifdef CONFIG_ADC_ADS1115_COMP_MODE
|
|
priv->cmdbyte |= ADS1115_COMP_MODE_MASK;
|
|
#endif
|
|
|
|
/* Set the default comparator polarity. */
|
|
|
|
#ifdef CONFIG_ADC_ADS1115_COMP_POL
|
|
priv->cmdbyte |= ADS1115_COMP_POL_MASK;
|
|
#endif
|
|
|
|
/* Set the default comparator latching. */
|
|
|
|
#ifdef CONFIG_ADC_ADS1115_COMP_LAT
|
|
priv->cmdbyte |= ADS1115_COMP_LAT_MASK;
|
|
#endif
|
|
|
|
/* Set the comparator queue. */
|
|
|
|
priv->cmdbyte |= CONFIG_ADC_ADS1115_COMP_QUE << ADS1115_COMP_QUE_SHIFT;
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_HI_THRESH_REGISTER,
|
|
htobe16(CONFIG_ADC_ADS1115_HI_THRESH));
|
|
if (ret != OK)
|
|
{
|
|
aerr("Failed to write high threshold register\n");
|
|
return ret;
|
|
}
|
|
|
|
return ads1115_write_register(priv, ADS1115_LO_THRESH_REGISTER,
|
|
htobe16(CONFIG_ADC_ADS1115_LO_THRESH));
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_trigger_conversion
|
|
*
|
|
* Description:
|
|
* Triggers a conversion on the specified channel.
|
|
*
|
|
* Input Parameters:
|
|
* priv - An ADS1115 device structure
|
|
* channel - The channel number to trigger conversion on (0-7)
|
|
*
|
|
* Return Value:
|
|
* OK on success; a negated errno on failure
|
|
*
|
|
* NOTE:
|
|
* Each channel corresponds to a differing mux configuration as defined in
|
|
* the datasheet.
|
|
*
|
|
* channel MUX Configuration
|
|
* 0 AINP = AIN0, AINN = AIN1
|
|
* 1 AINP = AIN0, AINN = AIN3
|
|
* 2 AINP = AIN1, AINN = AIN3
|
|
* 3 AINP = AIN2, AINN = AIN3
|
|
* 4 AINP = AIN0, AINN = GND
|
|
* 5 AINP = AIN1, AINN = GND
|
|
* 6 AINP = AIN2, AINN = GND
|
|
* 7 AINP = AIN3, AINN = GND
|
|
****************************************************************************/
|
|
|
|
static int ads1115_trigger_conversion(FAR struct ads1115_dev_s *priv,
|
|
FAR struct adc_msg_s *msg)
|
|
{
|
|
int ret = OK;
|
|
uint16_t channel_bits;
|
|
bool new_channel;
|
|
|
|
DEBUGASSERT(priv != NULL);
|
|
DEBUGASSERT(msg != NULL);
|
|
DEBUGASSERT(msg->am_channel <= ADS1115_NUM_CHANNELS);
|
|
|
|
channel_bits = ADS1115_CHANNEL_BITS(msg->am_channel);
|
|
new_channel = ((priv->cmdbyte & ADS1115_MUX_MASK) != channel_bits);
|
|
|
|
/* Check if our current channel is the same as the one that
|
|
* is set or if we are in one shot mode.
|
|
*/
|
|
|
|
if (new_channel || ADS1115_ONESHOT_MODE(priv))
|
|
{
|
|
/* Clear the current mux bits. */
|
|
|
|
priv->cmdbyte &= ~(ADS1115_MUX_MASK);
|
|
|
|
/* Set the new mux bits. */
|
|
|
|
priv->cmdbyte |= channel_bits;
|
|
|
|
/* Set the OS bit to start conversion. */
|
|
|
|
priv->cmdbyte |= ADS1115_OS_SHIFT;
|
|
|
|
/* Write to the configuration register. */
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_read_conversion
|
|
*
|
|
* Description:
|
|
* Reads the conversion result from the ADC.
|
|
*
|
|
* Input Parameters:
|
|
* priv - An ADS1115 device structure
|
|
* value - Pointer to store the conversion result
|
|
*
|
|
* Return Value:
|
|
* OK on success; a negated errno on failure
|
|
****************************************************************************/
|
|
|
|
static int ads1115_read_conversion(FAR struct ads1115_dev_s *priv,
|
|
FAR struct adc_msg_s *msg)
|
|
{
|
|
int ret = OK;
|
|
uint16_t buf;
|
|
int count = 0;
|
|
|
|
/* Read the configuration register until OS has been set to 1, indicating
|
|
* that the conversion value is ready.
|
|
*/
|
|
|
|
ret = ads1115_read_register(priv, ADS1115_CONFIG_REGISTER, &buf);
|
|
while (!(be16toh(buf) & ADS1115_OS_SHIFT) && count < 3)
|
|
{
|
|
up_udelay(ADS1115_CONVERSION_TIME);
|
|
ret = ads1115_read_register(priv, ADS1115_CONFIG_REGISTER, &buf);
|
|
count++;
|
|
}
|
|
|
|
/* If we are here, either the conversion completed or we encountered some
|
|
* error.
|
|
*/
|
|
|
|
if (ret != OK)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
if (count >= 3)
|
|
{
|
|
aerr("ADS1115 timed out waiting for conversion to finish\n");
|
|
return -ETIMEDOUT;
|
|
}
|
|
|
|
/* Read the conversion register. */
|
|
|
|
ret = ads1115_read_register(priv, ADS1115_CONVERSION_REGISTER, &buf);
|
|
msg->am_data = (uint32_t)betoh16(buf);
|
|
priv->cmdbyte &= ~(ADS1115_OS_SHIFT); /* Clear the OS bit. */
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_readchannel
|
|
*
|
|
* Description:
|
|
* Reads a conversion from the ADC.
|
|
*
|
|
* Input Parameters:
|
|
* priv - An ADS1115 device structure
|
|
* msg - An ADC message struct where the am_channel member contains the
|
|
* channel number to be read, and where the am_data member is where the
|
|
* reading is stored.
|
|
*
|
|
* NOTE:
|
|
* When switching between channels in continuous mode, old data may be
|
|
* read. Using the ALERT/RDY pin can avoid this.
|
|
*
|
|
* Each channel corresponds to a differing mux configuration as defined in
|
|
* the datasheet.
|
|
*
|
|
* msg->am_channel MUX Configuration
|
|
* 0 AINP = AIN0, AINN = AIN1
|
|
* 1 AINP = AIN0, AINN = AIN3
|
|
* 2 AINP = AIN1, AINN = AIN3
|
|
* 3 AINP = AIN2, AINN = AIN3
|
|
* 4 AINP = AIN0, AINN = GND
|
|
* 5 AINP = AIN1, AINN = GND
|
|
* 6 AINP = AIN2, AINN = GND
|
|
* 7 AINP = AIN3, AINN = GND
|
|
****************************************************************************/
|
|
|
|
static int ads1115_readchannel(FAR struct ads1115_dev_s *priv,
|
|
FAR struct adc_msg_s *msg)
|
|
{
|
|
int ret = OK;
|
|
|
|
DEBUGASSERT(priv != NULL);
|
|
DEBUGASSERT(msg != NULL);
|
|
DEBUGASSERT(msg->am_channel <= ADS1115_NUM_CHANNELS);
|
|
|
|
/* Trigger a conversion on the requested channel */
|
|
|
|
ret = ads1115_trigger_conversion(priv, msg);
|
|
if (ret)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
return ads1115_read_conversion(priv, msg);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_bind
|
|
*
|
|
* Description:
|
|
* Bind the upper-half driver callbacks to the lower-half implementation.
|
|
* This must be called early in order to receive ADC event notifications.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int ads1115_bind(FAR struct adc_dev_s *dev,
|
|
FAR const struct adc_callback_s *callback)
|
|
{
|
|
FAR struct ads1115_dev_s *priv = (FAR struct ads1115_dev_s *)dev->ad_priv;
|
|
DEBUGASSERT(priv != NULL);
|
|
priv->cb = callback;
|
|
return 0;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_reset
|
|
*
|
|
* Description:
|
|
* Reset the ADC device. Called early to initialize the hardware. This
|
|
* is called, before ao_setup() and on error conditions.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void ads1115_reset(FAR struct adc_dev_s *dev)
|
|
{
|
|
FAR struct ads1115_dev_s *priv = (FAR struct ads1115_dev_s *)dev->ad_priv;
|
|
cmdbyte_init(priv);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_setup
|
|
*
|
|
* Description:
|
|
* Configure the ADC. This method is called the first time that the ADC
|
|
* device is opened. This method will write the default configuration into
|
|
* the configuration register.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int ads1115_setup(FAR struct adc_dev_s *dev)
|
|
{
|
|
FAR struct ads1115_dev_s *priv = (FAR struct ads1115_dev_s *)dev->ad_priv;
|
|
return ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_shutdown
|
|
*
|
|
* Description:
|
|
* Disable the ADC. This method is called when the ADC device is closed.
|
|
* This method should reverse the operation of the setup method. The
|
|
* ADS1115 can be put into a power-down state by setting the mode bit to
|
|
* single-shot. This will stop the ADC from converting and reduce power
|
|
* consumption.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void ads1115_shutdown(FAR struct adc_dev_s *dev)
|
|
{
|
|
FAR struct ads1115_dev_s *priv = (FAR struct ads1115_dev_s *)dev->ad_priv;
|
|
priv->cmdbyte |= ADS1115_MODE_MASK;
|
|
ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_rxint
|
|
*
|
|
* Description:
|
|
* Needed for ADC upper-half compatibility but conversion interrupts
|
|
* are not supported by the ADS1115.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void ads1115_rxint(FAR struct adc_dev_s *dev, bool enable)
|
|
{
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_ioctl
|
|
*
|
|
* Description:
|
|
* All ioctl calls will be routed through this method.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int ads1115_ioctl(FAR struct adc_dev_s *dev, int cmd,
|
|
unsigned long arg)
|
|
{
|
|
FAR struct ads1115_dev_s *priv = (FAR struct ads1115_dev_s *)dev->ad_priv;
|
|
int ret = OK;
|
|
|
|
switch (cmd)
|
|
{
|
|
case ANIOC_TRIGGER:
|
|
{
|
|
struct adc_msg_s msg;
|
|
|
|
/* Read all channels in sequence */
|
|
|
|
for (uint8_t i = 0; i < ADS1115_NUM_CHANNELS; i++)
|
|
{
|
|
msg.am_channel = i;
|
|
ret = ads1115_readchannel(priv, &msg);
|
|
if (ret)
|
|
{
|
|
aerr("Error reading channel %d with error %d \n", i, ret);
|
|
break;
|
|
}
|
|
|
|
priv->cb->au_receive(dev, i, msg.am_data);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_PGA:
|
|
{
|
|
DEBUGASSERT(arg >= ADS1115_PGA1 && arg <= ADS1115_PGA8);
|
|
|
|
priv->cmdbyte &= ~ADS1115_PGA_MASK;
|
|
priv->cmdbyte |= arg << ADS1115_PGA_SHIFT;
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_MODE:
|
|
{
|
|
if (arg == ADS1115_MODE1)
|
|
{
|
|
priv->cmdbyte &= ~ADS1115_MODE_MASK;
|
|
}
|
|
else if (arg == ADS1115_MODE2)
|
|
{
|
|
priv->cmdbyte |= ADS1115_MODE_MASK;
|
|
}
|
|
else
|
|
{
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_DR:
|
|
{
|
|
DEBUGASSERT(arg >= ADS1115_DR1 && arg <= ADS1115_DR8);
|
|
priv->cmdbyte &= ~ADS1115_DR_MASK;
|
|
priv->cmdbyte |= arg << ADS1115_DR_SHIFT;
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_COMP_POL:
|
|
{
|
|
if (arg == ADS1115_COMP_POL1)
|
|
{
|
|
priv->cmdbyte &= ~ADS1115_COMP_POL_MASK;
|
|
}
|
|
else if (arg == ADS1115_COMP_POL2)
|
|
{
|
|
priv->cmdbyte |= ADS1115_COMP_POL_MASK;
|
|
}
|
|
else
|
|
{
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_COMP_MODE:
|
|
{
|
|
if (arg == ADS1115_COMP_MODE1)
|
|
{
|
|
priv->cmdbyte &= ~ADS1115_COMP_MODE_MASK;
|
|
}
|
|
else if (arg == ADS1115_COMP_MODE2)
|
|
{
|
|
priv->cmdbyte |= ADS1115_COMP_MODE_MASK;
|
|
}
|
|
else
|
|
{
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_COMP_LAT:
|
|
{
|
|
if (arg == ADS1115_COMP_LAT1)
|
|
{
|
|
priv->cmdbyte &= ~ADS1115_COMP_LAT_MASK;
|
|
}
|
|
else if (arg == ADS1115_COMP_LAT2)
|
|
{
|
|
priv->cmdbyte |= ADS1115_COMP_LAT_MASK;
|
|
}
|
|
else
|
|
{
|
|
ret = -EINVAL;
|
|
break;
|
|
}
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_COMP_QUEUE:
|
|
{
|
|
DEBUGASSERT(arg >= ADS1115_COMP_QUEUE1 &&
|
|
arg <= ADS1115_COMP_QUEUE4);
|
|
|
|
priv->cmdbyte &= ~ADS1115_COMP_QUE_MASK;
|
|
priv->cmdbyte |= arg << ADS1115_COMP_QUE_SHIFT;
|
|
|
|
ret = ads1115_write_register(priv, ADS1115_CONFIG_REGISTER,
|
|
htobe16(priv->cmdbyte));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_READ_CHANNEL:
|
|
{
|
|
ret = ads1115_readchannel(priv, (FAR struct adc_msg_s *)arg);
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_TRIGGER_CONVERSION:
|
|
{
|
|
ret = ads1115_trigger_conversion(priv, (FAR struct adc_msg_s *)arg);
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_READ_CHANNEL_NO_CONVERSION:
|
|
{
|
|
ret = ads1115_read_conversion(priv, (FAR struct adc_msg_s *)arg);
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_HI_THRESH:
|
|
{
|
|
DEBUGASSERT(arg >= 0 && arg <= UINT16_MAX);
|
|
ret = ads1115_write_register(priv, ADS1115_HI_THRESH_REGISTER,
|
|
htobe16(arg));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_ADS1115_SET_LO_THRESH:
|
|
{
|
|
DEBUGASSERT(arg >= 0 && arg <= UINT16_MAX);
|
|
ret = ads1115_write_register(priv, ADS1115_LO_THRESH_REGISTER,
|
|
htobe16(arg));
|
|
}
|
|
break;
|
|
|
|
case ANIOC_GET_NCHANNELS:
|
|
{
|
|
ret = ADS1115_NUM_CHANNELS;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ret = -ENOTTY;
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: ads1115_initialize
|
|
*
|
|
* Description:
|
|
* Initialize the selected ADC
|
|
*
|
|
* Input Parameters:
|
|
* i2c - Pointer to a valid I2C master struct.
|
|
* addr - I2C device address.
|
|
*
|
|
* Returned Value:
|
|
* Valid ADC device structure reference on success; a NULL on failure
|
|
*
|
|
* **************************************************************************/
|
|
|
|
FAR struct adc_dev_s *ads1115_initialize(FAR struct i2c_master_s *i2c,
|
|
uint8_t addr)
|
|
{
|
|
FAR struct ads1115_dev_s *priv;
|
|
FAR struct adc_dev_s *adcdev;
|
|
int ret;
|
|
|
|
DEBUGASSERT(i2c != NULL);
|
|
|
|
priv = kmm_malloc(sizeof(struct ads1115_dev_s));
|
|
if (priv == NULL)
|
|
{
|
|
aerr("ERROR: Failed to allocate ads1115_dev_s instance\n");
|
|
return NULL;
|
|
}
|
|
|
|
priv->cb = NULL;
|
|
priv->i2c = i2c;
|
|
priv->addr = addr;
|
|
priv->cmdbyte = 0;
|
|
|
|
ret = cmdbyte_init(priv);
|
|
if (ret != OK)
|
|
{
|
|
aerr("Failed to initialize ADS1115\n");
|
|
free(priv);
|
|
return NULL;
|
|
}
|
|
|
|
adcdev = kmm_malloc(sizeof(struct adc_dev_s));
|
|
if (adcdev == NULL)
|
|
{
|
|
aerr("ERROR: Failed to allocate adc_dev_s instance\n");
|
|
return NULL;
|
|
}
|
|
|
|
memset(adcdev, 0, sizeof(struct adc_dev_s));
|
|
adcdev->ad_ops = &g_ads1115ops;
|
|
adcdev->ad_priv = priv;
|
|
|
|
return adcdev;
|
|
}
|