mirror of
https://github.com/espressif/esp-idf.git
synced 2026-05-04 11:55:21 +02:00
driver(adc/dac): fix adc dac driver for esp32s2
1. update register file about adc; 2. fix adc driver; 3. add UT for adc/dac; See merge request espressif/esp-idf!7776
This commit is contained in:
@@ -0,0 +1,380 @@
|
||||
// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "esp_log.h"
|
||||
#include "sys/lock.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/rtc_cntl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
ESP_LOGE(ADC_TAG,"%s:%d\n",__FUNCTION__,__LINE__); \
|
||||
return ESP_FAIL; \
|
||||
} \
|
||||
})
|
||||
|
||||
static const char *ADC_TAG = "ADC";
|
||||
|
||||
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(ADC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||
|
||||
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||
|
||||
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc_digi_init(void)
|
||||
{
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_init();
|
||||
adc_hal_arbiter_config(&config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_deinit(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_init();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_controller_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config)
|
||||
{
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_arbiter_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ADC module controller.
|
||||
* There are five SAR ADC controllers:
|
||||
* Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes;
|
||||
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
|
||||
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
|
||||
*
|
||||
* @note Only ADC2 support arbiter to switch controllers automatically. Access to the ADC is based on the priority of the controller.
|
||||
* @note For ADC1, Controller access is mutually exclusive.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param ctrl ADC controller, Refer to `adc_controller_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_controller_t ctrl)
|
||||
{
|
||||
adc_arbiter_t config = {0};
|
||||
adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_set_controller(ADC_NUM_1, ctrl);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_set_controller(ADC_NUM_2, ctrl);
|
||||
switch (ctrl) {
|
||||
case ADC2_CTRL_FORCE_PWDET:
|
||||
config.pwdet_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC2_CTRL_PWDET);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_RTC:
|
||||
config.rtc_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_ULP:
|
||||
config.rtc_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_ULP);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_DIG:
|
||||
config.dig_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
|
||||
break;
|
||||
default:
|
||||
adc_hal_arbiter_config(&cfg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_start(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_enable();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_stop(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_disable();
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset FSM of adc digital controller.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_reset(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_reset();
|
||||
adc_hal_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_hal_digi_clear_pattern_table(ADC_NUM_2);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
adc_hal_digi_filter_reset(ADC_NUM_1);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
adc_hal_digi_filter_reset(ADC_NUM_2);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
adc_hal_digi_filter_set_factor(ADC_NUM_1, config->mode);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
adc_hal_digi_filter_set_factor(ADC_NUM_2, config->mode);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
config->adc_unit = ADC_UNIT_1;
|
||||
config->channel = ADC_CHANNEL_MAX;
|
||||
adc_hal_digi_filter_get_factor(ADC_NUM_1, &config->mode);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
config->adc_unit = ADC_UNIT_2;
|
||||
config->channel = ADC_CHANNEL_MAX;
|
||||
adc_hal_digi_filter_get_factor(ADC_NUM_2, &config->mode);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
adc_hal_digi_filter_enable(ADC_NUM_1, enable);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
adc_hal_digi_filter_enable(ADC_NUM_2, enable);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the filtered data of adc digital controller filter. For debug.
|
||||
* The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API.
|
||||
*
|
||||
* @note For ESP32S2, The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param idx Filter index.
|
||||
* @return Filtered data. if <0, the read data invalid.
|
||||
*/
|
||||
int adc_digi_filter_read_data(adc_digi_filter_idx_t idx)
|
||||
{
|
||||
if (idx == ADC_DIGI_FILTER_IDX0) {
|
||||
return adc_hal_digi_filter_read_data(ADC_NUM_1);
|
||||
} else if (idx == ADC_DIGI_FILTER_IDX1) {
|
||||
return adc_hal_digi_filter_read_data(ADC_NUM_2);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_MONITOR_IDX0) {
|
||||
adc_hal_digi_monitor_config(ADC_NUM_1, config);
|
||||
} else if (idx == ADC_DIGI_MONITOR_IDX1) {
|
||||
adc_hal_digi_monitor_config(ADC_NUM_2, config);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (idx == ADC_DIGI_MONITOR_IDX0) {
|
||||
adc_hal_digi_monitor_enable(ADC_NUM_1, enable);
|
||||
} else if (idx == ADC_DIGI_MONITOR_IDX1) {
|
||||
adc_hal_digi_monitor_enable(ADC_NUM_2, enable);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller intr setting */
|
||||
/**************************************/
|
||||
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_enable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_enable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_disable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_disable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_clear(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_clear(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ret = adc_hal_digi_get_intr_status(ADC_NUM_1);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
ret = adc_hal_digi_get_intr_status(ADC_NUM_2);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t s_isr_registered = 0;
|
||||
static intr_handle_t s_adc_isr_handle = NULL;
|
||||
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags)
|
||||
{
|
||||
ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL);
|
||||
|
||||
esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_isr_deregister(void)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (s_isr_registered) {
|
||||
ret = esp_intr_free(s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
@@ -0,0 +1,277 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Config ADC module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
* @note In normal use, there is no need to call this interface to config arbiter.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
|
||||
*/
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller initialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_init(void);
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller deinitialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Setting the digital controller.
|
||||
*
|
||||
* @param config Pointer to digital controller paramter. Refer to `adc_digi_config_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable digital controller to trigger the measurement.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief Disable digital controller to trigger the measurement.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_stop(void);
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
/**
|
||||
* @brief Reset adc digital controller filter.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
|
||||
|
||||
/**
|
||||
* @brief Set adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param enable Enable/Disable filter.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Config monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param config See ``adc_digi_monitor_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param enable True or false enable monitor.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller intr setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
|
||||
*/
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit);
|
||||
|
||||
/**
|
||||
* @brief Register ADC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Deregister ADC interrupt handler, the handler is an ISR.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG hander error.
|
||||
* - ESP_FAIL ISR not be registered.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_deregister(void);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Deprecated API
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Set I2S data source
|
||||
*
|
||||
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
|
||||
*
|
||||
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Initialize I2S ADC mode
|
||||
*
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
*
|
||||
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+7
-1
@@ -21,6 +21,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief temperature sensor range option.
|
||||
*/
|
||||
typedef enum {
|
||||
TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */
|
||||
TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */
|
||||
@@ -39,6 +42,9 @@ typedef struct {
|
||||
uint8_t clk_div; /*!< Default: 6 */
|
||||
} temp_sensor_config_t;
|
||||
|
||||
/**
|
||||
* @brief temperature sensor default setting.
|
||||
*/
|
||||
#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \
|
||||
.clk_div = 6}
|
||||
|
||||
@@ -74,7 +80,7 @@ esp_err_t temp_sensor_start(void);
|
||||
esp_err_t temp_sensor_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Read temperature sensor raw data.
|
||||
* @brief Read temperature sensor raw data.
|
||||
* @param tsens_out Pointer to raw data, Range: 0 ~ 255
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
+7
-7
@@ -233,7 +233,7 @@ esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_ma
|
||||
*
|
||||
* @param enable true(default): Enable the timeout check; false: Disable the timeout check.
|
||||
* @param threshold For all channels, the maximum value that will not be exceeded during normal operation.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
@@ -244,7 +244,7 @@ esp_err_t touch_pad_timeout_set(bool enable, uint32_t threshold);
|
||||
* If this API is not called, the touch FSM will stop the measurement after timeout interrupt.
|
||||
*
|
||||
* @note Call this API after finishes the exception handling by user.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
@@ -491,7 +491,7 @@ esp_err_t touch_pad_sleep_channel_get_info(touch_pad_sleep_channel_t *slp_config
|
||||
* e.g. The user should uses `touch_pad_sleep_channel_read_data` instead of `touch_pad_read_raw_data` to obtain the sleep channel reading.
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param enable true: enable sleep pad for touch sensor; false: disable sleep pad for touch sensor;
|
||||
* @param enable true: enable sleep pad for touch sensor; false: disable sleep pad for touch sensor;
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
@@ -502,9 +502,9 @@ esp_err_t touch_pad_sleep_channel_enable(touch_pad_t pad_num, bool enable);
|
||||
* The touch sensor can works in sleep mode to wake up sleep.
|
||||
*
|
||||
* @note ESP32S2 only support one sleep channel.
|
||||
*
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param enable true: enable proximity for sleep channel; false: disable proximity for sleep channel;
|
||||
* @param enable true: enable proximity for sleep channel; false: disable proximity for sleep channel;
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
@@ -515,7 +515,7 @@ esp_err_t touch_pad_sleep_channel_enable_proximity(touch_pad_t pad_num, bool ena
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
*
|
||||
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
|
||||
*
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param touch_thres touch sleep pad threshold
|
||||
* @return
|
||||
@@ -528,7 +528,7 @@ esp_err_t touch_pad_sleep_set_threshold(touch_pad_t pad_num, uint32_t touch_thre
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
*
|
||||
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
|
||||
*
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param touch_thres touch sleep pad threshold
|
||||
* @return
|
||||
@@ -18,11 +18,12 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/rtc_io_struct.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/sens_struct.h"
|
||||
#include "temp_sensor.h"
|
||||
#include "driver/temp_sensor.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
|
||||
static const char *TAG = "tsens";
|
||||
@@ -38,6 +39,18 @@ static const char *TAG = "tsens";
|
||||
#define TSENS_DAC_FACTOR (27.88)
|
||||
#define TSENS_SYS_OFFSET (20.52)
|
||||
|
||||
#include "i2c_rtc_clk.h"
|
||||
|
||||
#define ANA_CONFIG2_REG 0x6000E048
|
||||
#define ANA_CONFIG2_M (BIT(18))
|
||||
|
||||
#define I2C_ADC 0X69
|
||||
#define I2C_ADC_HOSTID 1
|
||||
|
||||
#define I2C_SARADC_TSENS_DAC 6
|
||||
#define I2C_SARADC_TSENS_DAC_MSB 3
|
||||
#define I2C_SARADC_TSENS_DAC_LSB 0
|
||||
|
||||
typedef struct {
|
||||
int index;
|
||||
int offset;
|
||||
@@ -60,7 +73,11 @@ static SemaphoreHandle_t rtc_tsens_mux = NULL;
|
||||
|
||||
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
|
||||
{
|
||||
// SENS.sar_tctrl.tsens_dac = dac_offset[tsens.dac_offset].set_val; // TODO: others MR resolve it.
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M);
|
||||
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18));
|
||||
SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16));
|
||||
I2C_WRITEREG_MASK_RTC(I2C_ADC, I2C_SARADC_TSENS_DAC, dac_offset[tsens.dac_offset].set_val);
|
||||
SENS.sar_tctrl.tsens_clk_div = tsens.clk_div;
|
||||
SENS.sar_tctrl.tsens_power_up_force = 1;
|
||||
SENS.sar_tctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT;
|
||||
@@ -77,9 +94,13 @@ esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
|
||||
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens)
|
||||
{
|
||||
TSENS_CHECK(tsens != NULL, ESP_ERR_INVALID_ARG);
|
||||
// tsens->dac_offset = SENS.sar_tctrl.tsens_dac; // TODO: others MR resolve it.
|
||||
for(int i=TSENS_DAC_L0; i<TSENS_DAC_MAX; i++) {
|
||||
if(tsens->dac_offset == dac_offset[i].set_val) {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PD_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_SAR_I2C_FORCE_PU_M);
|
||||
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, BIT(18));
|
||||
SET_PERI_REG_MASK(ANA_CONFIG2_REG, BIT(16));
|
||||
tsens->dac_offset = I2C_READREG_MASK_RTC(I2C_ADC, I2C_SARADC_TSENS_DAC);
|
||||
for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) {
|
||||
if (tsens->dac_offset == dac_offset[i].set_val) {
|
||||
tsens->dac_offset = dac_offset[i].index;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user