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
426438struct 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)
889908static 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
910931static 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
10281092static 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-
14841567BUILD_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
0 commit comments