-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expand support for ads1x4s0x series ADCs #83569
base: main
Are you sure you want to change the base?
Conversation
72406ed
to
533aea5
Compare
I've skipped through the list of precision ADC from TI (there are astonishingly plenty of them) and it looks like the pattern ads1x4s0x does not match something this driver doesn't (or shouldn't) support. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rename commit should already reflect the changes as well for instance in the CMakeLists.txt. Basically, the usual approach is not to squash the commits but keep them as they are, but ensure that every commit by itself can be used respectively built.
dts/bindings/adc/ti,ads114s08.yaml
Outdated
@@ -1,58 +1,8 @@ | |||
# Copyright (c) 2023 SILA Embedded Solutions GmbH | |||
# SPDX-License-Identifier: Apache-2.0 | |||
|
|||
description: Texas Instrument 12 channels 16 bit SPI ADC | |||
description: Texas Instrument 12 channels 24 bit SPI ADC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be the 16 bit version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
drivers/adc/adc_ads1x4s0x.c
Outdated
LOG_ERR("%s: positive channel input %i is invalid", dev->name, | ||
channel_cfg->input_positive); | ||
return -EINVAL; | ||
} | ||
|
||
if (channel_cfg->input_negative >= ADS114S0X_INPUT_SELECTION_AINCOM) { | ||
if (channel_cfg->input_negative >= config->channels \ | ||
&& channel_cfg->input_negative != ADS1X4S0X_INPUT_SELECTION_AINCOM) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be an or instead of an and?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually &&
is the correct choice. ADS124S06 and S08 both have the AINCOM to be 12, but S06 has only 0~5
usable channels whereas S08 has 0~11
all usable. So this is to check that for S06 devices the channels are within the range of {0~5, 12}
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, according to the TI datasheet, for S06 devices, the channel 6 and 7 are mapped to REFP1 and REFN1 so they are also usable, but I don't plan to write them into the code because it is quite confusing.
drivers/adc/adc_ads1x4s0x.c
Outdated
pin_selections[0] = channel_cfg->input_positive; | ||
pin_selections[1] = channel_cfg->input_negative; | ||
} else { | ||
LOG_DBG("%s: configuring channel for single ended measurement from input %i", | ||
dev->name, channel_cfg->input_positive); | ||
if (channel_cfg->input_positive >= ADS114S0X_INPUT_SELECTION_AINCOM) { | ||
if (channel_cfg->input_positive >= config->channels \ | ||
&& channel_cfg->input_positive != ADS1X4S0X_INPUT_SELECTION_AINCOM) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be an or instead of an and?
#define ADS114S0X_POWER_ON_RESET_TIME_IN_US 2200 | ||
#define ADS114S0X_VBIAS_PIN_MAX 7 | ||
#define ADS114S0X_VBIAS_PIN_MIN 0 | ||
#define ADS1X4S0X_CLK_FREQ_IN_KHZ 4096 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm definitely sure that it would be easier to review this if the renaming (especially all the defines, ... etc.) would be in a separate commit, because the actual changes are easily missed in this way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My apology... It was too late before I actually realized this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is rather difficult for me to figure out the actual changes within all the renaming. But as I'm neither a collaborator nor a maintainer I don't want to enforce something which is not required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anangl @henrikbrixandersen Do you think the renaming should be separated? And should each commit by itself successfully build, therefore removing the necessity of squashing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So here is the problem: If I rename a file but also change its content, there is a good chance that git cannot pick it up as a rename but instead treat it as a deletion and addition. This is especially troublesome since the name changes inside the file are more than 50% of the file itself.
What I can do is to consolidate all name changes inside a single commit, so the the code will function exactly the same. But the price is that commit will be rather unreadable (as you will see the deletion of a file and the addition of a new file but they are essentially the same). If you would trust me that the only thing I did in that commit is renaming, I will be happy to do so 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git mv
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope... I tried that.
Proposal: I do a commit that renames all variables first, then do a second commit that renames the files (and references to those files), just for clarity. These two rename commits will be squashed after this PR is approved, so it will be a large rename commit and should be able to build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine for me, but I also do not think the squash is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Now all these rename commits should be able to compile.
To rebase or not rebase, it's a problem and I shall leave to others to decide ;)
@@ -39,8 +39,8 @@ | |||
drdy-gpios = <&test_gpio 0 0>; | |||
start-sync-gpios = <&test_gpio 0 0>; | |||
|
|||
test_spi_ads114s08_gpio: ads114s0x_gpio { | |||
compatible = "ti,ads114s0x-gpio"; | |||
test_spi_ads114s08_gpio: ads1x4s0x_gpio { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add one instance of each binding to the build_all tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
drivers/adc/adc_ads1x4s0x.c
Outdated
/* | ||
* ADS114S06: 16 bit, 6 channels | ||
*/ | ||
#undef DT_DRV_COMPAT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a pretty similar issue with some DACs in the past, which were almost similar to each other expect number of channels and resolution. For this we ended up at an approach with a little bit less macro-foo, maybe you can take this as an inspiration? It would probably also help to tackle this kind of problems similarly throughout the project to get some consistency.
https://github.com/zephyrproject-rtos/zephyr/blob/main/drivers/dac/dac_ad56xx.c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also a nice idea!
I do somewhat dislike my current way because it requires me to move some functions to another header file.
The way in the code you referred to is not to completely redefine those functions by marcos but just redefine a static array holding the channel info.
My concern is: since the channel info is stored in the config structure, which is only passed to the functions in runtime, I think it is likely that the if
statement that branches over different chip types inside those functions will not be optimized out by the compiler.
In my case, the resolution-dependent functions include channel_setup
, read_sample
, adc_perform_read
, and validate_sequence
.
What's your take on this? Does it actually matter in most cases?
The other way I can think of is to just define those functions for different resolutions and put the pointers to them in the config structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is in the end a tradeoff between readability and runtime speed. But considering the loss is only one additional if I would go for better readability.
The size cost can be mitigate via putting functions which are only necessary in one chip variant in an #ifdef which depends on DT_HAS_..._ENABLED.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I implemented your proposal (using #ifdef
to save size).
@benediktibk Sorry about the force push... I scraped my macro commit. The only changes are around the lines you commented on. Also, I added two I think I'm ready for you to review again. |
cf5b735
to
83292de
Compare
…evices This commit shall be squashed into the next one before merging. Signed-off-by: Terry Geng <terry@terriex.com>
This commit works together with the previous one. Signed-off-by: Terry Geng <terry@terriex.com>
3abb537
to
a74d4f2
Compare
Refactor code for ADS114S0X (16 bit) to accommodate ADS124S0X (24 bit). Signed-off-by: Terry Geng <terry@terriex.com>
The existing support is only for
ADS114S08
(16-bit, 12-channel). It has one sisterADS114S06
(16-bit, 6-channel).Meanwhile, there are the 24-bit variations
ADS124S06
andADS124S08
, which are pin-to-pin compatible with theADS114S0X
series. Their documents are almost verbatim identical to theADS114S0X
series with a slightly different read format.This PR expands support to the remaining three chips,
ADS114S06
,ADS124S06
, andADS124S08
.Since this is a refactor involving many name changes, I separate the file rename into a commit to make the changes to the actual code more visible. It will be squashed before this PR is ready for merging.
As for the other two commits:
drivers/adc/adc_lmp90xxx.c
, introducing two variables in the config structure to save the resolution and number of channels for different variations. It also includes branching statements in the read functions to do the conversion from the raw data to integers correctly. It has a memory footprint ofThe second commit presents a different way of implementing the same. I define the read functions in a separate template file and populate the right resolution and channel number using macros. I would think this is more elegant since most boards will have only one type ofADS1X4S0X
and it's a waste of resources to save the resolution and channel numbers into the stack, and use extra branching statement to perform the check every time the read is invoked. It has a slightly smaller memory footprint compared to the previous one.I would leave the decision of which one to use to the reviewer. These three (or two) commits will be squashed into one before merging.Our reviewer @benediktibk has pointed out a better way out. I implemented that instead.
Testing
Tested with an ADS124S06 chip with a
rpi_pico
.The 16-bit read was tested with setting
compatible = "ti,ads114s06";
in the overlay. Since the 16-bit read will ignore the last byte of the response from the chip, it should still behave but with only reduced precision.My overlay file:
Note: the 24-bit read will not work with the examples in
samples/drivers/adc/
since they assume 16-bit input. One has to change the buffer toint32_t
to see the correct behavior.The correct conversion (assume the read buffer is
buf
):or