driver: sensor: adds basic support for analog devices ltc2990
This commit adds Kconfig variables to configure ADLTC2990. This commit adds basic driver code for analog devices ltc2990 sensor. Signed-off-by: Jilay Pandya <jilay.pandya@zeiss.com>
This commit is contained in:
parent
9fe56ed709
commit
3384ebb00f
8 changed files with 620 additions and 0 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
add_subdirectory_ifdef(CONFIG_A01NYUB a01nyub)
|
||||
add_subdirectory_ifdef(CONFIG_ADC_CMP_NPCX nuvoton_adc_cmp_npcx)
|
||||
add_subdirectory_ifdef(CONFIG_ADLTC2990 adltc2990)
|
||||
add_subdirectory_ifdef(CONFIG_ADT7310 adt7310)
|
||||
add_subdirectory_ifdef(CONFIG_ADT7420 adt7420)
|
||||
add_subdirectory_ifdef(CONFIG_ADXL345 adxl345)
|
||||
|
|
|
@ -58,6 +58,7 @@ config SENSOR_INFO
|
|||
comment "Device Drivers"
|
||||
|
||||
source "drivers/sensor/a01nyub/Kconfig"
|
||||
source "drivers/sensor/adltc2990/Kconfig"
|
||||
source "drivers/sensor/adt7310/Kconfig"
|
||||
source "drivers/sensor/adt7420/Kconfig"
|
||||
source "drivers/sensor/adxl345/Kconfig"
|
||||
|
|
6
drivers/sensor/adltc2990/CMakeLists.txt
Normal file
6
drivers/sensor/adltc2990/CMakeLists.txt
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Copyright(c) 2023 Carl Zeiss Meditec AG
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources(adltc2990.c)
|
13
drivers/sensor/adltc2990/Kconfig
Normal file
13
drivers/sensor/adltc2990/Kconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
# ADLTC2990 Quad I2C Voltage, Current and Temperature sensor configuration options
|
||||
|
||||
# Copyright(c) 2023 Carl Zeiss Meditec AG
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config ADLTC2990
|
||||
bool "ADLTC2990 Quad I2C Voltage, Current and Temperature Monitor"
|
||||
default y
|
||||
depends on DT_HAS_ADI_ADLTC2990_ENABLED
|
||||
select I2C
|
||||
help
|
||||
Enable the driver for Analog Devices LTC2990
|
||||
Quad I2C Voltage, Current and Temperature Monitor.
|
470
drivers/sensor/adltc2990/adltc2990.c
Normal file
470
drivers/sensor/adltc2990/adltc2990.c
Normal file
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT adi_adltc2990
|
||||
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
|
||||
#include "adltc2990_reg.h"
|
||||
#include "adltc2990.h"
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(adltc2990, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static enum adltc2990_monitoring_type adltc2990_get_v1_v2_measurement_modes(uint8_t mode_4_3,
|
||||
uint8_t mode_2_0)
|
||||
{
|
||||
if (mode_2_0 > ADLTC2990_MODE_2_0_MAX_VALUE || mode_4_3 > ADLTC2990_MODE_4_3_MAX_VALUE) {
|
||||
LOG_ERR("Invalid Measurement Mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode_4_3 == ADLTC2990_MEASURE_INTERNAL_TEMPERATURE_ONLY ||
|
||||
mode_4_3 == ADLTC2990_MEASURE_PINS_V3_V4_ONLY) {
|
||||
return NOTHING;
|
||||
}
|
||||
|
||||
enum adltc2990_monitoring_type type = NOTHING;
|
||||
|
||||
switch (mode_2_0) {
|
||||
case ADLTC2990_MODE_V1_V2_TR2:
|
||||
case ADLTC2990_MODE_V1_V2_V3_V4: {
|
||||
type = VOLTAGE_SINGLEENDED;
|
||||
break;
|
||||
}
|
||||
case ADLTC2990_MODE_V1_MINUS_V2_TR2:
|
||||
case ADLTC2990_MODE_V1_MINUS_V2_V3_V4:
|
||||
case ADLTC2990_MODE_V1_MINUS_V2_V3_MINUS_V4: {
|
||||
type = VOLTAGE_DIFFERENTIAL;
|
||||
break;
|
||||
}
|
||||
case ADLTC2990_MODE_TR1_V3_V4:
|
||||
case ADLTC2990_MODE_TR1_V3_MINUS_V4: {
|
||||
case ADLTC2990_MODE_TR1_TR2:
|
||||
type = TEMPERATURE;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static enum adltc2990_monitoring_type adltc2990_get_v3_v4_measurement_modes(uint8_t mode_4_3,
|
||||
uint8_t mode_2_0)
|
||||
{
|
||||
if (mode_2_0 > ADLTC2990_MODE_2_0_MAX_VALUE || mode_4_3 > ADLTC2990_MODE_4_3_MAX_VALUE) {
|
||||
LOG_ERR("Invalid Measurement Mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode_4_3 == ADLTC2990_MEASURE_INTERNAL_TEMPERATURE_ONLY ||
|
||||
mode_4_3 == ADLTC2990_MEASURE_PINS_V1_V2_ONLY) {
|
||||
return NOTHING;
|
||||
}
|
||||
|
||||
enum adltc2990_monitoring_type type = NOTHING;
|
||||
|
||||
switch (mode_2_0) {
|
||||
case ADLTC2990_MODE_V1_V2_TR2:
|
||||
case ADLTC2990_MODE_V1_MINUS_V2_TR2:
|
||||
case ADLTC2990_MODE_TR1_TR2: {
|
||||
type = TEMPERATURE;
|
||||
break;
|
||||
}
|
||||
|
||||
case ADLTC2990_MODE_V1_MINUS_V2_V3_V4:
|
||||
case ADLTC2990_MODE_TR1_V3_V4:
|
||||
case ADLTC2990_MODE_V1_V2_V3_V4: {
|
||||
type = VOLTAGE_SINGLEENDED;
|
||||
break;
|
||||
}
|
||||
case ADLTC2990_MODE_TR1_V3_MINUS_V4:
|
||||
case ADLTC2990_MODE_V1_MINUS_V2_V3_MINUS_V4: {
|
||||
type = VOLTAGE_DIFFERENTIAL;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool adltc2990_is_busy(const struct device *dev)
|
||||
{
|
||||
const struct adltc2990_config *cfg = dev->config;
|
||||
uint8_t status_reg = 0;
|
||||
|
||||
i2c_reg_read_byte_dt(&cfg->bus, ADLTC2990_REG_STATUS, &status_reg);
|
||||
return status_reg & BIT(0);
|
||||
}
|
||||
|
||||
static void adltc2990_get_v1_v2_val(const struct device *dev, struct sensor_value *val,
|
||||
uint8_t num_values, uint8_t *const offset_index)
|
||||
{
|
||||
struct adltc2990_data *data = dev->data;
|
||||
|
||||
for (uint8_t index = 0; index < num_values; index++) {
|
||||
val[index].val1 = data->pins_v1_v2_values[index] / 1000000;
|
||||
val[index].val2 = data->pins_v1_v2_values[index] % 1000000;
|
||||
*offset_index = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void adltc2990_get_v3_v4_val(const struct device *dev, struct sensor_value *val,
|
||||
uint8_t num_values, uint8_t const *const offset)
|
||||
{
|
||||
struct adltc2990_data *data = dev->data;
|
||||
|
||||
uint8_t offset_index = *offset;
|
||||
|
||||
for (uint8_t index = 0; index < num_values; index++) {
|
||||
val[index + offset_index].val1 = data->pins_v3_v4_values[index] / 1000000;
|
||||
val[index + offset_index].val2 = data->pins_v3_v4_values[index] % 1000000;
|
||||
}
|
||||
}
|
||||
|
||||
static int adltc2990_trigger_measurement(const struct device *dev)
|
||||
{
|
||||
const struct adltc2990_config *cfg = dev->config;
|
||||
|
||||
return i2c_reg_write_byte_dt(&cfg->bus, ADLTC2990_REG_TRIGGER, 0x1);
|
||||
}
|
||||
|
||||
static int32_t adltc2990_get_property_value(const struct device *dev,
|
||||
enum adltc2990_monitoring_type type,
|
||||
enum adltc2990_monitor_pins pin)
|
||||
{
|
||||
const struct adltc2990_config *cfg = dev->config;
|
||||
|
||||
uint8_t msb_value = 0, lsb_value = 0;
|
||||
uint8_t msb_address, lsb_address;
|
||||
|
||||
switch (pin) {
|
||||
case V1: {
|
||||
msb_address = ADLTC2990_REG_V1_MSB;
|
||||
lsb_address = ADLTC2990_REG_V1_LSB;
|
||||
break;
|
||||
}
|
||||
case V2: {
|
||||
msb_address = ADLTC2990_REG_V2_MSB;
|
||||
lsb_address = ADLTC2990_REG_V2_LSB;
|
||||
break;
|
||||
}
|
||||
case V3: {
|
||||
msb_address = ADLTC2990_REG_V3_MSB;
|
||||
lsb_address = ADLTC2990_REG_V3_LSB;
|
||||
break;
|
||||
}
|
||||
case V4: {
|
||||
msb_address = ADLTC2990_REG_V4_MSB;
|
||||
lsb_address = ADLTC2990_REG_V4_LSB;
|
||||
break;
|
||||
}
|
||||
case INTERNAL_TEMPERATURE: {
|
||||
msb_address = ADLTC2990_REG_INTERNAL_TEMP_MSB;
|
||||
lsb_address = ADLTC2990_REG_INTERNAL_TEMP_LSB;
|
||||
break;
|
||||
}
|
||||
case SUPPLY_VOLTAGE: {
|
||||
msb_address = ADLTC2990_REG_VCC_MSB;
|
||||
lsb_address = ADLTC2990_REG_VCC_LSB;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_ERR("Trying to access illegal register");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
i2c_reg_read_byte_dt(&cfg->bus, msb_address, &msb_value);
|
||||
i2c_reg_read_byte_dt(&cfg->bus, lsb_address, &lsb_value);
|
||||
uint16_t conversion_factor;
|
||||
uint8_t negative_bit_index;
|
||||
|
||||
if (type == VOLTAGE_SINGLEENDED) {
|
||||
conversion_factor = ADLTC2990_VOLTAGE_SINGLEENDED_CONVERSION_FACTOR;
|
||||
negative_bit_index = 14;
|
||||
} else if (type == VOLTAGE_DIFFERENTIAL) {
|
||||
conversion_factor = ADLTC2990_VOLTAGE_DIFFERENTIAL_CONVERSION_FACTOR;
|
||||
negative_bit_index = 14;
|
||||
} else if (type == TEMPERATURE) {
|
||||
conversion_factor = ADLTC2990_TEMPERATURE_CONVERSION_FACTOR;
|
||||
negative_bit_index = 12;
|
||||
} else {
|
||||
LOG_ERR("unknown type");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int16_t value = (msb_value<<8)+lsb_value;
|
||||
|
||||
int32_t voltage_value = (value << (31-negative_bit_index))>>(31-negative_bit_index);
|
||||
|
||||
return (voltage_value * conversion_factor) / 100;
|
||||
}
|
||||
|
||||
static int adltc2990_init(const struct device *dev)
|
||||
{
|
||||
const struct adltc2990_config *cfg = dev->config;
|
||||
|
||||
if (!i2c_is_ready_dt(&cfg->bus)) {
|
||||
LOG_ERR("I2C bus %s not ready", cfg->bus.bus->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
const uint8_t ctrl_reg_setting = cfg->temp_format << 7 | cfg->acq_format << 6 | 0 << 5 |
|
||||
cfg->measurement_mode[1] << 3 | cfg->measurement_mode[0];
|
||||
|
||||
LOG_DBG("Setting Control Register to: 0x%x", ctrl_reg_setting);
|
||||
int err = i2c_reg_write_byte_dt(&cfg->bus, ADLTC2990_REG_CONTROL, ctrl_reg_setting);
|
||||
|
||||
if (err < 0) {
|
||||
LOG_ERR("configuring for single bus failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
LOG_INF("Initializing ADLTC2990 with name %s", dev->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adltc2990_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
struct adltc2990_data *data = dev->data;
|
||||
const struct adltc2990_config *cfg = dev->config;
|
||||
enum adltc2990_monitoring_type mode_v1_v2 = adltc2990_get_v1_v2_measurement_modes(
|
||||
cfg->measurement_mode[1], cfg->measurement_mode[0]);
|
||||
enum adltc2990_monitoring_type mode_v3_v4 = adltc2990_get_v3_v4_measurement_modes(
|
||||
cfg->measurement_mode[1], cfg->measurement_mode[0]);
|
||||
|
||||
float voltage_divider_ratio;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_DIE_TEMP: {
|
||||
data->internal_temperature =
|
||||
adltc2990_get_property_value(dev, TEMPERATURE, INTERNAL_TEMPERATURE);
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_CURRENT: {
|
||||
if (!(mode_v1_v2 == VOLTAGE_DIFFERENTIAL || mode_v3_v4 == VOLTAGE_DIFFERENTIAL)) {
|
||||
LOG_ERR("Sensor is not configured to measure Current");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) {
|
||||
data->pins_v1_v2_values[0] =
|
||||
(adltc2990_get_property_value(dev, VOLTAGE_DIFFERENTIAL, V1) *
|
||||
ADLTC2990_MICROOHM_CONVERSION_FACTOR) /
|
||||
cfg->pins_v1_v2.pins_current_resistor;
|
||||
}
|
||||
if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) {
|
||||
data->pins_v3_v4_values[0] =
|
||||
(adltc2990_get_property_value(dev, VOLTAGE_DIFFERENTIAL, V3) *
|
||||
ADLTC2990_MICROOHM_CONVERSION_FACTOR) /
|
||||
cfg->pins_v3_v4.pins_current_resistor;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_VOLTAGE: {
|
||||
data->supply_voltage =
|
||||
adltc2990_get_property_value(dev, VOLTAGE_SINGLEENDED, SUPPLY_VOLTAGE) +
|
||||
2500000;
|
||||
|
||||
if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) {
|
||||
data->pins_v1_v2_values[0] =
|
||||
adltc2990_get_property_value(dev, VOLTAGE_DIFFERENTIAL, V1);
|
||||
} else if (mode_v1_v2 == VOLTAGE_SINGLEENDED) {
|
||||
uint32_t v1_r1 =
|
||||
cfg->pins_v1_v2.voltage_divider_resistors.v1_r1_r2[0];
|
||||
uint32_t v1_r2 =
|
||||
cfg->pins_v1_v2.voltage_divider_resistors.v2_r1_r2[1];
|
||||
voltage_divider_ratio = DIV_ROUND_CLOSEST(v1_r1 + v1_r2, v1_r2);
|
||||
data->pins_v1_v2_values[0] =
|
||||
adltc2990_get_property_value(dev, VOLTAGE_SINGLEENDED, V1) *
|
||||
voltage_divider_ratio;
|
||||
|
||||
uint32_t v2_r1 =
|
||||
cfg->pins_v1_v2.voltage_divider_resistors.v2_r1_r2[0];
|
||||
uint32_t v2_r2 =
|
||||
cfg->pins_v1_v2.voltage_divider_resistors.v2_r1_r2[1];
|
||||
voltage_divider_ratio = DIV_ROUND_CLOSEST(v2_r1 + v2_r2, v2_r2);
|
||||
data->pins_v1_v2_values[1] =
|
||||
adltc2990_get_property_value(dev, VOLTAGE_SINGLEENDED, V2) *
|
||||
voltage_divider_ratio;
|
||||
}
|
||||
|
||||
if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) {
|
||||
data->pins_v3_v4_values[0] =
|
||||
adltc2990_get_property_value(dev, VOLTAGE_DIFFERENTIAL, V3);
|
||||
} else if (mode_v3_v4 == VOLTAGE_SINGLEENDED) {
|
||||
uint32_t v3_r1 =
|
||||
cfg->pins_v3_v4.voltage_divider_resistors.v3_r1_r2[0];
|
||||
uint32_t v3_r2 =
|
||||
cfg->pins_v3_v4.voltage_divider_resistors.v3_r1_r2[1];
|
||||
voltage_divider_ratio = DIV_ROUND_CLOSEST(v3_r1 + v3_r2, v3_r2);
|
||||
data->pins_v3_v4_values[0] =
|
||||
adltc2990_get_property_value(dev, VOLTAGE_SINGLEENDED, V3) *
|
||||
voltage_divider_ratio;
|
||||
|
||||
uint32_t v4_r1 =
|
||||
cfg->pins_v3_v4.voltage_divider_resistors.v4_r1_r2[0];
|
||||
uint32_t v4_r2 =
|
||||
cfg->pins_v3_v4.voltage_divider_resistors.v4_r1_r2[1];
|
||||
voltage_divider_ratio = DIV_ROUND_CLOSEST((v4_r1 + v4_r2), v4_r2);
|
||||
data->pins_v3_v4_values[1] =
|
||||
adltc2990_get_property_value(dev, VOLTAGE_SINGLEENDED, V4) *
|
||||
voltage_divider_ratio;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_AMBIENT_TEMP: {
|
||||
if (!(mode_v1_v2 == TEMPERATURE || mode_v3_v4 == TEMPERATURE)) {
|
||||
LOG_ERR("Sensor is not configured to measure Ambient Temperature");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode_v1_v2 == TEMPERATURE) {
|
||||
data->pins_v1_v2_values[0] =
|
||||
adltc2990_get_property_value(dev, TEMPERATURE, V1);
|
||||
}
|
||||
if (mode_v3_v4 == TEMPERATURE) {
|
||||
data->pins_v3_v4_values[1] =
|
||||
adltc2990_get_property_value(dev, TEMPERATURE, V3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_ALL: {
|
||||
if (adltc2990_is_busy(dev)) {
|
||||
LOG_INF("ADLTC2990 conversion ongoing");
|
||||
return -EBUSY;
|
||||
}
|
||||
adltc2990_trigger_measurement(dev);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_ERR("does not measure channel: %d", chan);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adltc2990_channel_get(const struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
if (val == NULL) {
|
||||
LOG_ERR("Argument of type sensor_value* cannot be null ");
|
||||
return -EINVAL;
|
||||
}
|
||||
struct adltc2990_data *data = dev->data;
|
||||
const struct adltc2990_config *cfg = dev->config;
|
||||
enum adltc2990_monitoring_type mode_v1_v2 = adltc2990_get_v1_v2_measurement_modes(
|
||||
cfg->measurement_mode[1], cfg->measurement_mode[0]);
|
||||
enum adltc2990_monitoring_type mode_v3_v4 = adltc2990_get_v3_v4_measurement_modes(
|
||||
cfg->measurement_mode[1], cfg->measurement_mode[0]);
|
||||
|
||||
uint8_t offset_index = 0, num_values_v1_v2 = 0, num_values_v3_v4 = 0;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_DIE_TEMP: {
|
||||
val->val1 = data->internal_temperature / 10000;
|
||||
val->val2 = data->internal_temperature % 10000;
|
||||
LOG_DBG("Internal Temperature Value is:%d.%d", val->val1, val->val2);
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_VOLTAGE: {
|
||||
if (mode_v1_v2 == VOLTAGE_SINGLEENDED) {
|
||||
LOG_DBG("Getting V1,V2");
|
||||
num_values_v1_v2 = ADLTC2990_VOLTAGE_SINGLE_ENDED_VALUES;
|
||||
} else if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) {
|
||||
LOG_DBG("Getting V3-V4");
|
||||
num_values_v1_v2 = ADLTC2990_VOLTAGE_DIFF_VALUES;
|
||||
}
|
||||
if (mode_v3_v4 == VOLTAGE_SINGLEENDED) {
|
||||
LOG_DBG("Getting V3,V4");
|
||||
num_values_v3_v4 = ADLTC2990_VOLTAGE_SINGLE_ENDED_VALUES;
|
||||
} else if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) {
|
||||
LOG_DBG("Getting V3-V4");
|
||||
num_values_v3_v4 = ADLTC2990_VOLTAGE_DIFF_VALUES;
|
||||
}
|
||||
val[num_values_v1_v2 + num_values_v3_v4].val1 = data->supply_voltage / 1000000;
|
||||
val[num_values_v1_v2 + num_values_v3_v4].val2 = data->supply_voltage % 1000000;
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_CURRENT: {
|
||||
if (!(mode_v1_v2 == VOLTAGE_DIFFERENTIAL || mode_v3_v4 == VOLTAGE_DIFFERENTIAL)) {
|
||||
LOG_ERR("Sensor is not configured to measure Current");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL && mode_v3_v4 == VOLTAGE_DIFFERENTIAL) {
|
||||
LOG_DBG("Getting I12 and I34");
|
||||
num_values_v1_v2 = ADLTC2990_CURRENT_VALUES;
|
||||
num_values_v3_v4 = ADLTC2990_CURRENT_VALUES;
|
||||
} else if (mode_v1_v2 == VOLTAGE_DIFFERENTIAL) {
|
||||
LOG_DBG("Getting I12");
|
||||
num_values_v1_v2 = ADLTC2990_CURRENT_VALUES;
|
||||
} else if (mode_v3_v4 == VOLTAGE_DIFFERENTIAL) {
|
||||
LOG_DBG("Getting I34");
|
||||
num_values_v3_v4 = ADLTC2990_CURRENT_VALUES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SENSOR_CHAN_AMBIENT_TEMP: {
|
||||
if (!(mode_v1_v2 == TEMPERATURE || mode_v3_v4 == TEMPERATURE)) {
|
||||
LOG_ERR("Sensor is not configured to measure Ambient Temperature");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (mode_v1_v2 == TEMPERATURE && mode_v3_v4 == TEMPERATURE) {
|
||||
LOG_DBG("Getting T12 and T34");
|
||||
num_values_v1_v2 = ADLTC2990_TEMP_VALUES;
|
||||
num_values_v3_v4 = ADLTC2990_TEMP_VALUES;
|
||||
} else if (mode_v1_v2 == TEMPERATURE) {
|
||||
LOG_DBG("Getting T12");
|
||||
num_values_v1_v2 = ADLTC2990_TEMP_VALUES;
|
||||
} else if (mode_v3_v4 == TEMPERATURE) {
|
||||
LOG_DBG("Getting T34");
|
||||
num_values_v3_v4 = ADLTC2990_TEMP_VALUES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
}
|
||||
|
||||
adltc2990_get_v1_v2_val(dev, val, num_values_v1_v2, &offset_index);
|
||||
adltc2990_get_v3_v4_val(dev, val, num_values_v3_v4, &offset_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api adltc2990_driver_api = {
|
||||
.sample_fetch = adltc2990_sample_fetch,
|
||||
.channel_get = adltc2990_channel_get,
|
||||
};
|
||||
|
||||
#define ADLTC2990_DEFINE(inst) \
|
||||
static struct adltc2990_data adltc2990_data_##inst; \
|
||||
static const struct adltc2990_config adltc2990_config_##inst = { \
|
||||
.bus = I2C_DT_SPEC_INST_GET(inst), \
|
||||
.temp_format = DT_INST_PROP(inst, temperature_format), \
|
||||
.acq_format = DT_INST_PROP(inst, acquistion_format), \
|
||||
.measurement_mode = DT_INST_PROP(inst, measurement_mode), \
|
||||
.pins_v1_v2.pins_current_resistor = \
|
||||
DT_INST_PROP_OR(inst, pins_v1_v2_current_resistor, 1), \
|
||||
.pins_v1_v2.voltage_divider_resistors.v1_r1_r2 = \
|
||||
DT_INST_PROP_OR(inst, pin_v1_voltage_divider_resistors, NULL), \
|
||||
.pins_v1_v2.voltage_divider_resistors.v2_r1_r2 = \
|
||||
DT_INST_PROP_OR(inst, pin_v2_voltage_divider_resistors, NULL), \
|
||||
.pins_v3_v4.pins_current_resistor = \
|
||||
DT_INST_PROP_OR(inst, pins_v3_v4_current_resistor, 1), \
|
||||
.pins_v3_v4.voltage_divider_resistors.v3_r1_r2 = \
|
||||
DT_INST_PROP_OR(inst, pin_v3_voltage_divider_resistors, NULL), \
|
||||
.pins_v3_v4.voltage_divider_resistors.v4_r1_r2 = \
|
||||
DT_INST_PROP_OR(inst, pin_v4_voltage_divider_resistors, NULL)}; \
|
||||
\
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, adltc2990_init, NULL, &adltc2990_data_##inst, \
|
||||
&adltc2990_config_##inst, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &adltc2990_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(ADLTC2990_DEFINE)
|
63
drivers/sensor/adltc2990/adltc2990.h
Normal file
63
drivers/sensor/adltc2990/adltc2990.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_ADLTC2990_H
|
||||
#define ZEPHYR_DRIVERS_SENSOR_ADLTC2990_H
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
|
||||
enum adltc2990_monitor_pins {
|
||||
V1,
|
||||
V2,
|
||||
V3,
|
||||
V4,
|
||||
INTERNAL_TEMPERATURE,
|
||||
SUPPLY_VOLTAGE
|
||||
} adltc2990_monitor_pins;
|
||||
|
||||
enum adltc2990_monitoring_type {
|
||||
NOTHING,
|
||||
VOLTAGE_DIFFERENTIAL,
|
||||
VOLTAGE_SINGLEENDED,
|
||||
TEMPERATURE
|
||||
} adltc2990_monitoring_type;
|
||||
|
||||
union voltage_divider_resistors {
|
||||
struct {
|
||||
uint32_t v1_r1_r2[2];
|
||||
uint32_t v2_r1_r2[2];
|
||||
};
|
||||
struct {
|
||||
uint32_t v3_r1_r2[2];
|
||||
uint32_t v4_r1_r2[2];
|
||||
};
|
||||
};
|
||||
|
||||
struct pins_configuration {
|
||||
uint32_t pins_current_resistor;
|
||||
union voltage_divider_resistors voltage_divider_resistors;
|
||||
};
|
||||
|
||||
struct adltc2990_data {
|
||||
int32_t internal_temperature;
|
||||
int32_t supply_voltage;
|
||||
int32_t pins_v1_v2_values[2];
|
||||
int32_t pins_v3_v4_values[2];
|
||||
};
|
||||
|
||||
struct adltc2990_config {
|
||||
struct i2c_dt_spec bus;
|
||||
uint8_t temp_format;
|
||||
uint8_t acq_format;
|
||||
uint8_t measurement_mode[2];
|
||||
struct pins_configuration pins_v1_v2;
|
||||
struct pins_configuration pins_v3_v4;
|
||||
};
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_ADLTC2990_H */
|
54
drivers/sensor/adltc2990/adltc2990_reg.h
Normal file
54
drivers/sensor/adltc2990/adltc2990_reg.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_ADLTC2990_REG_H
|
||||
#define ZEPHYR_DRIVERS_SENSOR_ADLTC2990_REG_H
|
||||
|
||||
#define ADLTC2990_REG_STATUS 0x00U
|
||||
#define ADLTC2990_REG_CONTROL 0x01U
|
||||
#define ADLTC2990_REG_TRIGGER 0x02U
|
||||
#define ADLTC2990_REG_UNUSED 0x03U
|
||||
#define ADLTC2990_REG_INTERNAL_TEMP_MSB 0x04U
|
||||
#define ADLTC2990_REG_INTERNAL_TEMP_LSB 0x05U
|
||||
#define ADLTC2990_REG_V1_MSB 0x06U
|
||||
#define ADLTC2990_REG_V1_LSB 0x07U
|
||||
#define ADLTC2990_REG_V2_MSB 0x08U
|
||||
#define ADLTC2990_REG_V2_LSB 0x09U
|
||||
#define ADLTC2990_REG_V3_MSB 0x0AU
|
||||
#define ADLTC2990_REG_V3_LSB 0x0BU
|
||||
#define ADLTC2990_REG_V4_MSB 0x0CU
|
||||
#define ADLTC2990_REG_V4_LSB 0x0DU
|
||||
#define ADLTC2990_REG_VCC_MSB 0x0EU
|
||||
#define ADLTC2990_REG_VCC_LSB 0x0FU
|
||||
|
||||
#define ADLTC2990_VOLTAGE_SINGLE_ENDED_VALUES 2U
|
||||
#define ADLTC2990_VOLTAGE_DIFF_VALUES 1U
|
||||
#define ADLTC2990_TEMP_VALUES 1U
|
||||
#define ADLTC2990_CURRENT_VALUES 1U
|
||||
#define ADLTC2990_MICROOHM_CONVERSION_FACTOR 1000000U
|
||||
|
||||
#define ADLTC2990_MODE_V1_V2_TR2 0U
|
||||
#define ADLTC2990_MODE_V1_MINUS_V2_TR2 1U
|
||||
#define ADLTC2990_MODE_V1_MINUS_V2_V3_V4 2U
|
||||
#define ADLTC2990_MODE_TR1_V3_V4 3U
|
||||
#define ADLTC2990_MODE_TR1_V3_MINUS_V4 4U
|
||||
#define ADLTC2990_MODE_TR1_TR2 5U
|
||||
#define ADLTC2990_MODE_V1_MINUS_V2_V3_MINUS_V4 6U
|
||||
#define ADLTC2990_MODE_V1_V2_V3_V4 7U
|
||||
|
||||
#define ADLTC2990_MEASURE_INTERNAL_TEMPERATURE_ONLY 0U
|
||||
#define ADLTC2990_MEASURE_PINS_V1_V2_ONLY 1U
|
||||
#define ADLTC2990_MEASURE_PINS_V3_V4_ONLY 2U
|
||||
#define ADLTC2990_MEASURE_ALL_PINS_PER_MODE_2_0 3U
|
||||
|
||||
#define ADLTC2990_VOLTAGE_SINGLEENDED_CONVERSION_FACTOR 30518
|
||||
#define ADLTC2990_VOLTAGE_DIFFERENTIAL_CONVERSION_FACTOR 1942
|
||||
#define ADLTC2990_TEMPERATURE_CONVERSION_FACTOR 62500
|
||||
|
||||
#define ADLTC2990_MODE_2_0_MAX_VALUE 7U
|
||||
#define ADLTC2990_MODE_4_3_MAX_VALUE 3U
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_SENSOR_ADLTC2990_REG_H */
|
Loading…
Add table
Add a link
Reference in a new issue