Skip to content

Commit 49308e4

Browse files
TerryGengkartben
authored andcommitted
drivers: adc: ads1x4s0x: Add ADS124S0X support into existing drivers
Refactor code for ADS114S08 (12 ch, 16 bit) to accommodate ADS114S06 (6 ch, 16 bit), ADS124S06 (6 ch, 24 bit), and ADS124S08 (12 ch, 24 bit). Signed-off-by: Terry Geng <[email protected]>
1 parent cbcb2d8 commit 49308e4

File tree

12 files changed

+365
-150
lines changed

12 files changed

+365
-150
lines changed

doc/releases/release-notes-4.1.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,9 @@ New Drivers
302302
* :dtcompatible:`ti,ads131m02`
303303
* :dtcompatible:`ti,tla2022`
304304
* :dtcompatible:`ti,tla2024`
305+
* :dtcompatible:`ti,ads114s06`
306+
* :dtcompatible:`ti,ads124s06`
307+
* :dtcompatible:`ti,ads124s08`
305308

306309
* ARM architecture
307310

drivers/adc/Kconfig.ads1x4s0x

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
menuconfig ADC_ADS1X4S0X
66
bool "Texas instruments ADS1X4S0X"
77
default y
8-
depends on DT_HAS_TI_ADS1X4S08_ENABLED
8+
depends on DT_HAS_TI_ADS114S06_ENABLED || DT_HAS_TI_ADS114S08_ENABLED \
9+
|| DT_HAS_TI_ADS124S06_ENABLED || DT_HAS_TI_ADS124S08_ENABLED
910
select SPI
1011
select ADC_CONFIGURABLE_INPUTS
1112
select ADC_CONFIGURABLE_EXCITATION_CURRENT_SOURCE_PIN

drivers/adc/adc_ads1x4s0x.c

Lines changed: 168 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
#include <zephyr/sys/byteorder.h>
1717
#include <zephyr/sys/util.h>
1818

19+
#define ADS1X4S0X_HAS_16_BIT_DEV \
20+
(DT_HAS_COMPAT_STATUS_OKAY(ti_ads114s06) || DT_HAS_COMPAT_STATUS_OKAY(ti_ads114s08))
21+
#define ADS1X4S0X_HAS_24_BIT_DEV \
22+
(DT_HAS_COMPAT_STATUS_OKAY(ti_ads124s06) || DT_HAS_COMPAT_STATUS_OKAY(ti_ads124s08))
23+
1924
#define ADC_CONTEXT_USES_KERNEL_TIMER 1
2025
#define ADC_CONTEXT_WAIT_FOR_COMPLETION_TIMEOUT \
2126
K_MSEC(CONFIG_ADC_ADS1X4S0X_WAIT_FOR_COMPLETION_TIMEOUT_MS)
@@ -28,7 +33,6 @@ LOG_MODULE_REGISTER(ads1x4s0x, CONFIG_ADC_LOG_LEVEL);
2833
#define ADS1X4S0X_START_SYNC_PULSE_DURATION_IN_CLOCK_CYCLES 4
2934
#define ADS1X4S0X_SETUP_TIME_IN_CLOCK_CYCLES 32
3035
#define ADS1X4S0X_INPUT_SELECTION_AINCOM 12
31-
#define ADS1X4S0X_RESOLUTION 16
3236
#define ADS1X4S0X_REF_INTERNAL 2500
3337
#define ADS1X4S0X_GPIO_MAX 3
3438
#define ADS1X4S0X_POWER_ON_RESET_TIME_IN_US 2200
@@ -73,12 +77,18 @@ enum ads1x4s0x_register {
7377
ADS1X4S0X_REGISTER_IDACMUX = 0x07,
7478
ADS1X4S0X_REGISTER_VBIAS = 0x08,
7579
ADS1X4S0X_REGISTER_SYS = 0x09,
76-
ADS1X4S0X_REGISTER_OFCAL0 = 0x0B,
77-
ADS1X4S0X_REGISTER_OFCAL1 = 0x0C,
78-
ADS1X4S0X_REGISTER_FSCAL0 = 0x0E,
79-
ADS1X4S0X_REGISTER_FSCAL1 = 0x0F,
8080
ADS1X4S0X_REGISTER_GPIODAT = 0x10,
8181
ADS1X4S0X_REGISTER_GPIOCON = 0x11,
82+
ADS114S0X_REGISTER_OFCAL0 = 0x0B,
83+
ADS114S0X_REGISTER_OFCAL1 = 0x0C,
84+
ADS114S0X_REGISTER_FSCAL0 = 0x0E,
85+
ADS114S0X_REGISTER_FSCAL1 = 0x0F,
86+
ADS124S0X_REGISTER_OFCAL0 = 0x0A,
87+
ADS124S0X_REGISTER_OFCAL1 = 0x0B,
88+
ADS124S0X_REGISTER_OFCAL2 = 0x0C,
89+
ADS124S0X_REGISTER_FSCAL0 = 0x0E,
90+
ADS124S0X_REGISTER_FSCAL1 = 0x0F,
91+
ADS124S0X_REGISTER_FSCAL2 = 0x0F,
8292
};
8393

8494
#define ADS1X4S0X_REGISTER_GET_VALUE(value, pos, length) \
@@ -421,6 +431,8 @@ struct ads1x4s0x_config {
421431
const struct gpio_dt_spec gpio_start_sync;
422432
int idac_current;
423433
uint8_t vbias_level;
434+
uint8_t channels;
435+
uint8_t resolution;
424436
};
425437

426438
struct ads1x4s0x_data {
@@ -431,8 +443,8 @@ struct ads1x4s0x_data {
431443
struct gpio_callback callback_data_ready;
432444
struct k_sem data_ready_signal;
433445
struct k_sem acquire_signal;
434-
int16_t *buffer;
435-
int16_t *buffer_ptr;
446+
void *buffer;
447+
void *buffer_ptr;
436448
#if CONFIG_ADC_ADS1X4S0X_GPIO
437449
struct k_mutex gpio_lock;
438450
uint8_t gpio_enabled; /* one bit per GPIO, 1 = enabled */
@@ -680,13 +692,15 @@ static int ads1x4s0x_channel_setup(const struct device *dev,
680692
LOG_DBG("%s: configuring channel for a differential measurement from the pins (p, "
681693
"n) (%i, %i)",
682694
dev->name, channel_cfg->input_positive, channel_cfg->input_negative);
683-
if (channel_cfg->input_positive >= ADS1X4S0X_INPUT_SELECTION_AINCOM) {
695+
if (channel_cfg->input_positive >= config->channels &&
696+
channel_cfg->input_positive != ADS1X4S0X_INPUT_SELECTION_AINCOM) {
684697
LOG_ERR("%s: positive channel input %i is invalid", dev->name,
685698
channel_cfg->input_positive);
686699
return -EINVAL;
687700
}
688701

689-
if (channel_cfg->input_negative >= ADS1X4S0X_INPUT_SELECTION_AINCOM) {
702+
if (channel_cfg->input_negative >= config->channels &&
703+
channel_cfg->input_negative != ADS1X4S0X_INPUT_SELECTION_AINCOM) {
690704
LOG_ERR("%s: negative channel input %i is invalid", dev->name,
691705
channel_cfg->input_negative);
692706
return -EINVAL;
@@ -705,7 +719,8 @@ static int ads1x4s0x_channel_setup(const struct device *dev,
705719
} else {
706720
LOG_DBG("%s: configuring channel for single ended measurement from input %i",
707721
dev->name, channel_cfg->input_positive);
708-
if (channel_cfg->input_positive >= ADS1X4S0X_INPUT_SELECTION_AINCOM) {
722+
if (channel_cfg->input_positive >= config->channels &&
723+
channel_cfg->input_positive != ADS1X4S0X_INPUT_SELECTION_AINCOM) {
709724
LOG_ERR("%s: channel input %i is invalid", dev->name,
710725
channel_cfg->input_positive);
711726
return -EINVAL;
@@ -871,9 +886,13 @@ static int ads1x4s0x_channel_setup(const struct device *dev,
871886
return 0;
872887
}
873888

874-
static int ads1x4s0x_validate_buffer_size(const struct adc_sequence *sequence)
889+
static int ads1x4s0x_validate_buffer_size(const struct device *dev,
890+
const struct adc_sequence *sequence)
875891
{
876-
size_t needed = sizeof(int16_t);
892+
const struct ads1x4s0x_config *config = dev->config;
893+
size_t needed;
894+
895+
needed = (config->resolution > 16) ? sizeof(int32_t) : sizeof(int16_t);
877896

878897
if (sequence->options) {
879898
needed *= (1 + sequence->options->extra_samplings);
@@ -889,7 +908,9 @@ static int ads1x4s0x_validate_buffer_size(const struct adc_sequence *sequence)
889908
static int ads1x4s0x_validate_sequence(const struct device *dev,
890909
const struct adc_sequence *sequence)
891910
{
892-
if (sequence->resolution != ADS1X4S0X_RESOLUTION) {
911+
const struct ads1x4s0x_config *config = dev->config;
912+
913+
if (sequence->resolution != config->resolution) {
893914
LOG_ERR("%s: invalid resolution", dev->name);
894915
return -EINVAL;
895916
}
@@ -904,7 +925,7 @@ static int ads1x4s0x_validate_sequence(const struct device *dev,
904925
return -EINVAL;
905926
}
906927

907-
return ads1x4s0x_validate_buffer_size(sequence);
928+
return ads1x4s0x_validate_buffer_size(dev, sequence);
908929
}
909930

910931
static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
@@ -988,18 +1009,19 @@ static int ads1x4s0x_wait_data_ready(const struct device *dev)
9881009
return k_sem_take(&data->data_ready_signal, ADC_CONTEXT_WAIT_FOR_COMPLETION_TIMEOUT);
9891010
}
9901011

991-
static int ads1x4s0x_read_sample(const struct device *dev, uint16_t *buffer)
1012+
#if ADS1X4S0X_HAS_16_BIT_DEV
1013+
static int ads1x4s0x_read_sample_16(const struct device *dev, int16_t *buffer)
9921014
{
9931015
const struct ads1x4s0x_config *config = dev->config;
9941016
uint8_t buffer_tx[3];
9951017
uint8_t buffer_rx[ARRAY_SIZE(buffer_tx)];
9961018
const struct spi_buf tx_buf[] = {{
9971019
.buf = buffer_tx,
998-
.len = ARRAY_SIZE(buffer_tx),
1020+
.len = 3,
9991021
}};
10001022
const struct spi_buf rx_buf[] = {{
10011023
.buf = buffer_rx,
1002-
.len = ARRAY_SIZE(buffer_rx),
1024+
.len = 3,
10031025
}};
10041026
const struct spi_buf_set tx = {
10051027
.buffers = tx_buf,
@@ -1024,11 +1046,55 @@ static int ads1x4s0x_read_sample(const struct device *dev, uint16_t *buffer)
10241046

10251047
return 0;
10261048
}
1049+
#endif
1050+
1051+
#if ADS1X4S0X_HAS_24_BIT_DEV
1052+
static int ads1x4s0x_read_sample_24(const struct device *dev, int32_t *buffer)
1053+
{
1054+
const struct ads1x4s0x_config *config = dev->config;
1055+
uint8_t buffer_tx[5] = {0};
1056+
uint8_t buffer_rx[ARRAY_SIZE(buffer_tx)];
1057+
const struct spi_buf tx_buf[] = {{
1058+
.buf = buffer_tx,
1059+
.len = 4,
1060+
}};
1061+
const struct spi_buf rx_buf[] = {{
1062+
.buf = buffer_rx,
1063+
.len = 4,
1064+
}};
1065+
const struct spi_buf_set tx = {
1066+
.buffers = tx_buf,
1067+
.count = ARRAY_SIZE(tx_buf),
1068+
};
1069+
const struct spi_buf_set rx = {
1070+
.buffers = rx_buf,
1071+
.count = ARRAY_SIZE(rx_buf),
1072+
};
1073+
1074+
buffer_tx[0] = (uint8_t)ADS1X4S0X_COMMAND_RDATA;
1075+
1076+
int result = spi_transceive_dt(&config->bus, &tx, &rx);
1077+
1078+
if (result != 0) {
1079+
LOG_ERR("%s: spi_transceive failed with error %i", dev->name, result);
1080+
return result;
1081+
}
1082+
1083+
*buffer = (int32_t)sys_get_be32(buffer_rx + 1) >> 8;
1084+
1085+
LOG_DBG("%s: read ADC sample 0x%02X%02X%02X", dev->name, *(buffer_rx + 1), *(buffer_rx + 2),
1086+
*(buffer_rx + 3));
1087+
1088+
return 0;
1089+
}
1090+
#endif
10271091

10281092
static int ads1x4s0x_adc_perform_read(const struct device *dev)
10291093
{
10301094
int result;
1095+
const struct ads1x4s0x_config *config = dev->config;
10311096
struct ads1x4s0x_data *data = dev->data;
1097+
void *buffer = data->buffer;
10321098

10331099
k_sem_take(&data->acquire_signal, K_FOREVER);
10341100
k_sem_reset(&data->data_ready_signal);
@@ -1047,17 +1113,34 @@ static int ads1x4s0x_adc_perform_read(const struct device *dev)
10471113
return result;
10481114
}
10491115

1050-
result = ads1x4s0x_read_sample(dev, data->buffer);
1051-
if (result != 0) {
1052-
LOG_ERR("%s: reading sample failed", dev->name);
1053-
adc_context_complete(&data->ctx, result);
1054-
return result;
1116+
#if ADS1X4S0X_HAS_24_BIT_DEV
1117+
if (config->resolution == 24) {
1118+
result = ads1x4s0x_read_sample_24(dev, (int32_t *)data->buffer);
1119+
1120+
if (result == 0) {
1121+
buffer = (int32_t *)buffer + 1;
1122+
adc_context_on_sampling_done(&data->ctx, dev);
1123+
return 0;
1124+
}
1125+
10551126
}
1127+
#endif
10561128

1057-
data->buffer++;
1129+
#if ADS1X4S0X_HAS_16_BIT_DEV
1130+
if (config->resolution == 16) {
1131+
result = ads1x4s0x_read_sample_16(dev, (int16_t *)data->buffer);
10581132

1059-
adc_context_on_sampling_done(&data->ctx, dev);
1133+
if (result == 0) {
1134+
buffer = (int16_t *)buffer + 1;
1135+
adc_context_on_sampling_done(&data->ctx, dev);
1136+
return 0;
1137+
}
1138+
1139+
}
1140+
#endif
10601141

1142+
LOG_ERR("%s: reading sample failed", dev->name);
1143+
adc_context_complete(&data->ctx, result);
10611144
return result;
10621145
}
10631146

@@ -1112,6 +1195,7 @@ static void ads1x4s0x_acquisition_thread(void *p1, void *p2, void *p3)
11121195
ARG_UNUSED(p3);
11131196

11141197
const struct device *dev = p1;
1198+
11151199
while (true) {
11161200
ads1x4s0x_adc_perform_read(dev);
11171201
}
@@ -1480,29 +1564,68 @@ static DEVICE_API(adc, api) = {
14801564
.read_async = ads1x4s0x_adc_read_async,
14811565
#endif
14821566
};
1483-
14841567
BUILD_ASSERT(CONFIG_ADC_INIT_PRIORITY > CONFIG_SPI_INIT_PRIORITY,
14851568
"CONFIG_ADC_INIT_PRIORITY must be higher than CONFIG_SPI_INIT_PRIORITY");
14861569

1570+
#define ADC_ADS1X4S0X_INST_DEFINE(n, name, ch, res) \
1571+
IF_ENABLED( \
1572+
CONFIG_ADC_ASYNC, \
1573+
(static K_KERNEL_STACK_DEFINE( \
1574+
thread_stack_##name##_##n, \
1575+
CONFIG_ADC_ADS1X4S0X_ACQUISITION_THREAD_STACK_SIZE);) \
1576+
) \
1577+
static const struct ads1x4s0x_config config_##name##_##n = { \
1578+
.bus = SPI_DT_SPEC_INST_GET( \
1579+
n, SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(8), 0), \
1580+
IF_ENABLED(CONFIG_ADC_ASYNC, (.stack = thread_stack_##n,)) \
1581+
.gpio_reset = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \
1582+
.gpio_data_ready = GPIO_DT_SPEC_INST_GET(n, drdy_gpios), \
1583+
.gpio_start_sync = GPIO_DT_SPEC_INST_GET_OR(n, start_sync_gpios, {0}), \
1584+
.idac_current = DT_INST_PROP(n, idac_current), \
1585+
.vbias_level = DT_INST_PROP(n, vbias_level), \
1586+
.vbias_level = DT_INST_PROP(n, vbias_level), \
1587+
.resolution = res, \
1588+
.channels = ch, \
1589+
}; \
1590+
static struct ads1x4s0x_data data_##name##_##n; \
1591+
DEVICE_DT_INST_DEFINE(n, ads1x4s0x_init, NULL, &data_##name##_##n, &config_##name##_##n, \
1592+
POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, &api);
1593+
1594+
/*
1595+
* ADS114S06: 16 bit, 6 channels
1596+
*/
1597+
#define DT_DRV_COMPAT ti_ads114s06
1598+
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
1599+
#define ADC_ADS114S06_INST_DEFINE(n) ADC_ADS1X4S0X_INST_DEFINE(n, ti_ads114s06, 6, 16)
1600+
DT_INST_FOREACH_STATUS_OKAY(ADC_ADS114S06_INST_DEFINE);
1601+
#endif
1602+
1603+
/*
1604+
* ADS114S08: 16 bit, 12 channels
1605+
*/
1606+
#undef DT_DRV_COMPAT
14871607
#define DT_DRV_COMPAT ti_ads114s08
1608+
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
1609+
#define ADC_ADS114S08_INST_DEFINE(n) ADC_ADS1X4S0X_INST_DEFINE(n, ti_ads114s08, 12, 16)
1610+
DT_INST_FOREACH_STATUS_OKAY(ADC_ADS114S08_INST_DEFINE);
1611+
#endif
1612+
1613+
/*
1614+
* ADS124S06: 24 bit, 6 channels
1615+
*/
1616+
#undef DT_DRV_COMPAT
1617+
#define DT_DRV_COMPAT ti_ads124s06
1618+
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
1619+
#define ADC_ADS124S06_INST_DEFINE(n) ADC_ADS1X4S0X_INST_DEFINE(n, ti_ads124s06, 6, 24)
1620+
DT_INST_FOREACH_STATUS_OKAY(ADC_ADS124S06_INST_DEFINE);
1621+
#endif
14881622

1489-
#define ADC_ADS1X4S0X_INST_DEFINE(n) \
1490-
IF_ENABLED( \
1491-
CONFIG_ADC_ASYNC, \
1492-
(static K_KERNEL_STACK_DEFINE( \
1493-
thread_stack_##n, CONFIG_ADC_ADS1X4S0X_ACQUISITION_THREAD_STACK_SIZE);)) \
1494-
static const struct ads1x4s0x_config config_##n = { \
1495-
.bus = SPI_DT_SPEC_INST_GET( \
1496-
n, SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(8), 0), \
1497-
IF_ENABLED(CONFIG_ADC_ASYNC, (.stack = thread_stack_##n,)) \
1498-
.gpio_reset = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \
1499-
.gpio_data_ready = GPIO_DT_SPEC_INST_GET(n, drdy_gpios), \
1500-
.gpio_start_sync = GPIO_DT_SPEC_INST_GET_OR(n, start_sync_gpios, {0}), \
1501-
.idac_current = DT_INST_PROP(n, idac_current), \
1502-
.vbias_level = DT_INST_PROP(n, vbias_level), \
1503-
}; \
1504-
static struct ads1x4s0x_data data_##n; \
1505-
DEVICE_DT_INST_DEFINE(n, ads1x4s0x_init, NULL, &data_##n, &config_##n, POST_KERNEL, \
1506-
CONFIG_ADC_INIT_PRIORITY, &api);
1507-
1508-
DT_INST_FOREACH_STATUS_OKAY(ADC_ADS1X4S0X_INST_DEFINE);
1623+
/*
1624+
* ADS124S08: 24 bit, 12 channels
1625+
*/
1626+
#undef DT_DRV_COMPAT
1627+
#define DT_DRV_COMPAT ti_ads124s08
1628+
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
1629+
#define ADC_ADS124S08_INST_DEFINE(n) ADC_ADS1X4S0X_INST_DEFINE(n, ti_ads124s08, 12, 24)
1630+
DT_INST_FOREACH_STATUS_OKAY(ADC_ADS124S08_INST_DEFINE);
1631+
#endif

dts/bindings/adc/ti,ads114s06.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2024 The Zephyr Project Contributors
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Texas Instrument 6 channels 16 bit SPI ADC
5+
6+
compatible: "ti,ads114s06"
7+
8+
include: ti,ads1x4s0x-base.yaml

0 commit comments

Comments
 (0)