1- /* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
1+ /* SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
22 *
33 * SPDX-License-Identifier: Apache-2.0
44 */
@@ -22,10 +22,19 @@ static const char *TAG = "adc_button";
2222#define NO_OF_SAMPLES CONFIG_ADC_BUTTON_SAMPLE_TIMES //Multisampling
2323
2424/*!< Using atten bigger than 6db by default, it will be 11db or 12db in different target */
25+ #if SOC_ADC_ATTEN_NUM >= 4
2526#define DEFAULT_ADC_ATTEN (ADC_ATTEN_DB_6 + 1)
27+ #else
28+ #define DEFAULT_ADC_ATTEN ADC_ATTEN_DB_0
29+ #endif
2630
31+ #ifdef SOC_ADC_RTC_MAX_BITWIDTH
2732#define ADC_BUTTON_WIDTH SOC_ADC_RTC_MAX_BITWIDTH
28- #define ADC_BUTTON_CHANNEL_MAX SOC_ADC_MAX_CHANNEL_NUM
33+ #else
34+ #define ADC_BUTTON_WIDTH SOC_ADC_DIGI_MAX_BITWIDTH
35+ #endif
36+
37+ #define ADC_BUTTON_CHANNEL_MAX (adc_unit ) SOC_ADC_CHANNEL_NUM(adc_unit)
2938#define ADC_BUTTON_ATTEN DEFAULT_ADC_ATTEN
3039
3140#define ADC_BUTTON_MAX_CHANNEL CONFIG_ADC_BUTTON_MAX_CHANNEL
@@ -95,7 +104,6 @@ static int find_channel(adc_unit_t unit_id, uint8_t channel)
95104 }
96105 return -1 ;
97106}
98-
99107static bool adc_calibration_init (adc_unit_t unit , adc_atten_t atten , adc_cali_handle_t * out_handle )
100108{
101109 adc_cali_handle_t handle = NULL ;
@@ -135,19 +143,21 @@ static bool adc_calibration_init(adc_unit_t unit, adc_atten_t atten, adc_cali_ha
135143 * out_handle = handle ;
136144 if (ret == ESP_OK ) {
137145 ESP_LOGI (TAG , "Calibration Success" );
138- } else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated ) {
139- ESP_LOGW (TAG , "eFuse not burnt, skip software calibration" );
140146 } else if (ret == ESP_ERR_NOT_SUPPORTED ) {
141- ESP_LOGW (TAG , "Calibration not supported" );
147+ ESP_LOGW (TAG , "ADC calibration is not supported, skip software calibration " );
142148 } else {
143- ESP_LOGE (TAG , "Invalid arg or no memory" );
149+ ESP_LOGE (TAG , "ADC calibration init failed: %s" , esp_err_to_name ( ret ) );
144150 }
145151
146152 return calibrated ;
147153}
148154
149155static bool adc_calibration_deinit (adc_cali_handle_t handle )
150156{
157+ if (handle == NULL ) {
158+ return true;
159+ }
160+
151161#if ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED
152162 if (adc_cali_delete_scheme_curve_fitting (handle ) == ESP_OK ) {
153163 return true;
@@ -166,7 +176,7 @@ static bool adc_calibration_deinit(adc_cali_handle_t handle)
166176esp_err_t button_adc_del (button_driver_t * button_driver )
167177{
168178 button_adc_obj * adc_btn = __containerof (button_driver , button_adc_obj , base );
169- ESP_RETURN_ON_FALSE (adc_btn -> ch < ADC_BUTTON_CHANNEL_MAX , ESP_ERR_INVALID_ARG , TAG , "channel out of range" );
179+ ESP_RETURN_ON_FALSE (adc_btn -> ch < ADC_BUTTON_CHANNEL_MAX ( adc_btn -> unit_id ) , ESP_ERR_INVALID_ARG , TAG , "channel out of range" );
170180 ESP_RETURN_ON_FALSE (adc_btn -> index < ADC_BUTTON_MAX_BUTTON , ESP_ERR_INVALID_ARG , TAG , "button_index out of range" );
171181
172182 int ch_index = find_channel (adc_btn -> unit_id , adc_btn -> ch );
@@ -184,7 +194,7 @@ esp_err_t button_adc_del(button_driver_t *button_driver)
184194 }
185195 if (unused_button == ADC_BUTTON_MAX_BUTTON && g_button .unit [adc_btn -> unit_id ].ch [ch_index ].is_init ) { /**< if all button is unused, deinit the channel */
186196 g_button .unit [adc_btn -> unit_id ].ch [ch_index ].is_init = 0 ;
187- g_button .unit [adc_btn -> unit_id ].ch [ch_index ].channel = ADC_BUTTON_CHANNEL_MAX ;
197+ g_button .unit [adc_btn -> unit_id ].ch [ch_index ].channel = ADC_BUTTON_CHANNEL_MAX ( adc_btn -> unit_id ) ;
188198 ESP_LOGD (TAG , "all button is unused on channel%d, deinit the channel" , g_button .unit [adc_btn -> unit_id ].ch [ch_index ].channel );
189199 }
190200
@@ -222,9 +232,27 @@ static uint32_t get_adc_voltage(adc_unit_t unit_id, uint8_t channel)
222232 adc_reading /= NO_OF_SAMPLES ;
223233 //Convert adc_reading to voltage in mV
224234 int voltage = 0 ;
225- adc_cali_raw_to_voltage (g_button .unit [unit_id ].adc_cali_handle , adc_reading , & voltage );
226- ESP_LOGV (TAG , "Raw: %" PRIu32 "\tVoltage: %dmV" , adc_reading , voltage );
227- return voltage ;
235+ if (g_button .unit [unit_id ].adc_cali_handle != NULL ) {
236+ esp_err_t ret = adc_cali_raw_to_voltage (g_button .unit [unit_id ].adc_cali_handle , adc_reading , & voltage );
237+ if (ret != ESP_OK ) {
238+ ESP_LOGE (TAG , "ADC calibration conversion failed: %s" , esp_err_to_name (ret ));
239+ return 0 ;
240+ }
241+ } else {
242+ #if CONFIG_IDF_TARGET_ESP32S31
243+ // Keep the offset correction in signed arithmetic to avoid unsigned underflow near zero.
244+ voltage = (int32_t )adc_reading * 4 * 1000 / 4393 - 2 ;
245+ if (voltage < 0 ) {
246+ voltage = 0 ;
247+ }
248+ #else
249+ // No calibration handle means the chip does not support software calibration; return 0 to indicate that the voltage value is not available.
250+ voltage = 0 ;
251+ #endif
252+ }
253+
254+ ESP_LOGD (TAG , "Raw: %" PRIu32 "\tVoltage: %dmV" , adc_reading , voltage );
255+ return (uint32_t )voltage ;
228256}
229257
230258uint8_t button_adc_get_key_level (button_driver_t * button_driver )
@@ -233,7 +261,7 @@ uint8_t button_adc_get_key_level(button_driver_t *button_driver)
233261 static uint16_t vol = 0 ;
234262 uint32_t ch = adc_btn -> ch ;
235263 uint32_t index = adc_btn -> index ;
236- ESP_RETURN_ON_FALSE (ch < ADC_BUTTON_CHANNEL_MAX , 0 , TAG , "channel out of range" );
264+ ESP_RETURN_ON_FALSE (ch < ADC_BUTTON_CHANNEL_MAX ( adc_btn -> unit_id ) , 0 , TAG , "channel out of range" );
237265 ESP_RETURN_ON_FALSE (index < ADC_BUTTON_MAX_BUTTON , 0 , TAG , "button_index out of range" );
238266
239267 int ch_index = find_channel (adc_btn -> unit_id , ch );
@@ -257,7 +285,7 @@ esp_err_t iot_button_new_adc_device(const button_config_t *button_config, const
257285 esp_err_t ret = ESP_OK ;
258286 ESP_RETURN_ON_FALSE (button_config && adc_config && ret_button , ESP_ERR_INVALID_ARG , TAG , "Invalid argument" );
259287 ESP_RETURN_ON_FALSE (adc_config -> unit_id < ADC_UNIT_NUM , ESP_ERR_INVALID_ARG , TAG , "adc_handle out of range" );
260- ESP_RETURN_ON_FALSE (adc_config -> adc_channel < ADC_BUTTON_CHANNEL_MAX , ESP_ERR_INVALID_ARG , TAG , "channel out of range" );
288+ ESP_RETURN_ON_FALSE (adc_config -> adc_channel < ADC_BUTTON_CHANNEL_MAX ( adc_config -> unit_id ) , ESP_ERR_INVALID_ARG , TAG , "channel out of range" );
261289 ESP_RETURN_ON_FALSE (adc_config -> button_index < ADC_BUTTON_MAX_BUTTON , ESP_ERR_INVALID_ARG , TAG , "button_index out of range" );
262290 ESP_RETURN_ON_FALSE (adc_config -> max > 0 , ESP_ERR_INVALID_ARG , TAG , "key max voltage invalid" );
263291 button_adc_obj * adc_btn = calloc (1 , sizeof (button_adc_obj ));
0 commit comments