diff --git a/drivers/adc/adc_common.c b/drivers/adc/adc_common.c index eed4ec4ead6..8b8f9c4802a 100644 --- a/drivers/adc/adc_common.c +++ b/drivers/adc/adc_common.c @@ -6,36 +6,52 @@ #include -int adc_gain_invert(enum adc_gain gain, - int32_t *value) +struct gain_desc { + uint8_t mul; + uint8_t div; +}; +static const struct gain_desc gains[] = { + [ADC_GAIN_1_6] = {.mul = 6, .div = 1}, + [ADC_GAIN_1_5] = {.mul = 5, .div = 1}, + [ADC_GAIN_1_4] = {.mul = 4, .div = 1}, + [ADC_GAIN_2_7] = {.mul = 7, .div = 2}, + [ADC_GAIN_1_3] = {.mul = 3, .div = 1}, + [ADC_GAIN_2_5] = {.mul = 5, .div = 2}, + [ADC_GAIN_1_2] = {.mul = 2, .div = 1}, + [ADC_GAIN_2_3] = {.mul = 3, .div = 2}, + [ADC_GAIN_4_5] = {.mul = 5, .div = 4}, + [ADC_GAIN_1] = {.mul = 1, .div = 1}, + [ADC_GAIN_2] = {.mul = 1, .div = 2}, + [ADC_GAIN_3] = {.mul = 1, .div = 3}, + [ADC_GAIN_4] = {.mul = 1, .div = 4}, + [ADC_GAIN_6] = {.mul = 1, .div = 6}, + [ADC_GAIN_8] = {.mul = 1, .div = 8}, + [ADC_GAIN_12] = {.mul = 1, .div = 12}, + [ADC_GAIN_16] = {.mul = 1, .div = 16}, + [ADC_GAIN_24] = {.mul = 1, .div = 24}, + [ADC_GAIN_32] = {.mul = 1, .div = 32}, + [ADC_GAIN_64] = {.mul = 1, .div = 64}, + [ADC_GAIN_128] = {.mul = 1, .div = 128}, +}; + +int adc_gain_invert(enum adc_gain gain, int32_t *value) +{ + int rv = -EINVAL; + + if ((uint8_t)gain < ARRAY_SIZE(gains)) { + const struct gain_desc *gdp = &gains[gain]; + + if ((gdp->mul != 0) && (gdp->div != 0)) { + *value = (gdp->mul * *value) / gdp->div; + rv = 0; + } + } + + return rv; +} + +int adc_gain_invert_64(enum adc_gain gain, int64_t *value) { - struct gain_desc { - uint8_t mul; - uint8_t div; - }; - static const struct gain_desc gains[] = { - [ADC_GAIN_1_6] = {.mul = 6, .div = 1}, - [ADC_GAIN_1_5] = {.mul = 5, .div = 1}, - [ADC_GAIN_1_4] = {.mul = 4, .div = 1}, - [ADC_GAIN_2_7] = {.mul = 7, .div = 2}, - [ADC_GAIN_1_3] = {.mul = 3, .div = 1}, - [ADC_GAIN_2_5] = {.mul = 5, .div = 2}, - [ADC_GAIN_1_2] = {.mul = 2, .div = 1}, - [ADC_GAIN_2_3] = {.mul = 3, .div = 2}, - [ADC_GAIN_4_5] = {.mul = 5, .div = 4}, - [ADC_GAIN_1] = {.mul = 1, .div = 1}, - [ADC_GAIN_2] = {.mul = 1, .div = 2}, - [ADC_GAIN_3] = {.mul = 1, .div = 3}, - [ADC_GAIN_4] = {.mul = 1, .div = 4}, - [ADC_GAIN_6] = {.mul = 1, .div = 6}, - [ADC_GAIN_8] = {.mul = 1, .div = 8}, - [ADC_GAIN_12] = {.mul = 1, .div = 12}, - [ADC_GAIN_16] = {.mul = 1, .div = 16}, - [ADC_GAIN_24] = {.mul = 1, .div = 24}, - [ADC_GAIN_32] = {.mul = 1, .div = 32}, - [ADC_GAIN_64] = {.mul = 1, .div = 64}, - [ADC_GAIN_128] = {.mul = 1, .div = 128}, - }; int rv = -EINVAL; if ((uint8_t)gain < ARRAY_SIZE(gains)) { diff --git a/include/zephyr/drivers/adc.h b/include/zephyr/drivers/adc.h index 7eabbe17937..1930bc32c2e 100644 --- a/include/zephyr/drivers/adc.h +++ b/include/zephyr/drivers/adc.h @@ -71,8 +71,25 @@ enum adc_gain { * @retval 0 if the gain was successfully reversed * @retval -EINVAL if the gain could not be interpreted */ -int adc_gain_invert(enum adc_gain gain, - int32_t *value); +int adc_gain_invert(enum adc_gain gain, int32_t *value); + +/** + * @brief Invert the application of gain to a measurement value. + * + * For example, if the gain passed in is ADC_GAIN_1_6 and the + * referenced value is 10, the value after the function returns is 60. + * + * @param gain the gain used to amplify the input signal. + * + * @param value a pointer to a value that initially has the effect of + * the applied gain but has that effect removed when this function + * successfully returns. If the gain cannot be reversed the value + * remains unchanged. + * + * @retval 0 if the gain was successfully reversed + * @retval -EINVAL if the gain could not be interpreted + */ +int adc_gain_invert_64(enum adc_gain gain, int64_t *value); /** @brief ADC references. */ enum adc_reference {