mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
driver(i2s): fix broken i2s adc mode
1. Move i2s reset code from i2s_stop to i2s_start. 2. add RTC API to set sw mode for ADC 3. add description for adc_power_always_on() 4. add lock for i2s dma and RTC ADC functions. 5. add ADC read task in example reported from bbs: https://esp32.com/viewtopic.php?f=13&t=3490&p=17522#p17522 reported from github: https://github.com/espressif/esp-idf/issues/1333 Also update some deprecated APIs for ADC.
This commit is contained in:
parent
94ec3c8e53
commit
945d2e697c
73
components/driver/adc1_i2s_private.h
Normal file
73
components/driver/adc1_i2s_private.h
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2015-2016 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.
|
||||
|
||||
#ifndef _DRIVER_ADC1_I2S_PRIVATE_H_
|
||||
#define _DRIVER_ADC1_I2S_PRIVATE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Force power on for SAR ADC.
|
||||
* This function should be called for the scenario in which ADC are controlled by digital function like DMA.
|
||||
* When the ADC power is always on, RTC FSM can still be functional.
|
||||
* This is an internal API for I2S module to call to enable I2S-ADC function.
|
||||
* Note that adc_power_off() can still power down ADC.
|
||||
*/
|
||||
void adc_power_always_on();
|
||||
|
||||
/**
|
||||
* @brief For I2S dma to claim the usage of ADC1.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_i2s_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* The I2S module may have to wait for a short time for the current conversion (if exist) to finish.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
|
||||
*/
|
||||
esp_err_t adc1_i2s_mode_acquire();
|
||||
|
||||
/**
|
||||
* @brief For ADC1 to claim the usage of ADC1.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_adc_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* The ADC1 may have to wait for some time for the I2S read operation to finish.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_TIMEOUT reserved for future use. Currently the function will wait until success.
|
||||
*/
|
||||
esp_err_t adc1_adc_mode_acquire();
|
||||
|
||||
/**
|
||||
* @brief to let other tasks use the ADC1 when I2S is not work.
|
||||
*
|
||||
* Other tasks will be forbidden to use ADC1 between ``adc1_adc/i2s_mode_acquire`` and ``adc1_i2s_release``.
|
||||
* Call this function to release the occupation of ADC1
|
||||
*
|
||||
* @return always return ESP_OK.
|
||||
*/
|
||||
esp_err_t adc1_lock_release();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_DRIVER_ADC1_I2S_PRIVATE_H_*/
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/dac.h"
|
||||
#include "adc1_i2s_private.h"
|
||||
|
||||
#include "esp_intr.h"
|
||||
#include "esp_err.h"
|
||||
@ -84,12 +85,14 @@ typedef struct {
|
||||
int bits_per_sample; /*!< Bits per sample*/
|
||||
i2s_mode_t mode; /*!< I2S Working mode*/
|
||||
int use_apll; /*!< I2S use APLL clock */
|
||||
uint32_t sample_rate; /*!< I2S sample rate */
|
||||
} i2s_obj_t;
|
||||
|
||||
static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
|
||||
static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
|
||||
static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED};
|
||||
|
||||
static int _i2s_adc_unit = -1;
|
||||
static int _i2s_adc_channel = -1;
|
||||
/**
|
||||
* @brief Pre define APLL parameters, save compute time
|
||||
* | bits_per_sample | rate | sdm0 | sdm1 | sdm2 | odir
|
||||
@ -322,12 +325,11 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
if (p_i2s_obj[i2s_num] == NULL) {
|
||||
ESP_LOGE(I2S_TAG, "Not initialized yet");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
p_i2s_obj[i2s_num]->sample_rate = rate;
|
||||
double clkmdiv = (double)I2S_BASE_CLK / (rate * factor);
|
||||
|
||||
if (clkmdiv > 256) {
|
||||
@ -652,6 +654,18 @@ esp_err_t i2s_start(i2s_port_t i2s_num)
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
//start DMA link
|
||||
I2S_ENTER_CRITICAL();
|
||||
i2s_reset_fifo(i2s_num);
|
||||
//reset dma
|
||||
I2S[i2s_num]->lc_conf.in_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.in_rst = 0;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 0;
|
||||
|
||||
I2S[i2s_num]->conf.tx_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_reset = 0;
|
||||
I2S[i2s_num]->conf.rx_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_reset = 0;
|
||||
|
||||
esp_intr_disable(p_i2s_obj[i2s_num]->i2s_isr_handle);
|
||||
I2S[i2s_num]->int_clr.val = 0xFFFFFFFF;
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
@ -685,17 +699,6 @@ esp_err_t i2s_stop(i2s_port_t i2s_num)
|
||||
i2s_disable_rx_intr(i2s_num);
|
||||
}
|
||||
I2S[i2s_num]->int_clr.val = I2S[i2s_num]->int_st.val; //clear pending interrupt
|
||||
i2s_reset_fifo(i2s_num);
|
||||
//reset dma
|
||||
I2S[i2s_num]->lc_conf.in_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.in_rst = 0;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 1;
|
||||
I2S[i2s_num]->lc_conf.out_rst = 0;
|
||||
|
||||
I2S[i2s_num]->conf.tx_reset = 1;
|
||||
I2S[i2s_num]->conf.tx_reset = 0;
|
||||
I2S[i2s_num]->conf.rx_reset = 1;
|
||||
I2S[i2s_num]->conf.rx_reset = 0;
|
||||
I2S_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -722,10 +725,18 @@ esp_err_t i2s_set_dac_mode(i2s_dac_mode_t dac_mode)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t _i2s_adc_mode_recover()
|
||||
{
|
||||
I2S_CHECK(((_i2s_adc_unit != -1) && (_i2s_adc_channel != -1)), "i2s ADC recover error, not initialized...", ESP_ERR_INVALID_ARG);
|
||||
return adc_i2s_mode_init(_i2s_adc_unit, _i2s_adc_channel);
|
||||
}
|
||||
|
||||
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel)
|
||||
{
|
||||
I2S_CHECK((adc_unit < ADC_UNIT_2), "i2s ADC unit error, only support ADC1 for now", ESP_ERR_INVALID_ARG);
|
||||
// For now, we only support SAR ADC1.
|
||||
_i2s_adc_unit = adc_unit;
|
||||
_i2s_adc_channel = adc_channel;
|
||||
return adc_i2s_mode_init(adc_unit, adc_channel);
|
||||
}
|
||||
|
||||
@ -864,7 +875,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
//initialize the specific ADC channel.
|
||||
//in the current stage, we only support ADC1 and single channel mode.
|
||||
//In default data mode, the ADC data is in 12-bit resolution mode.
|
||||
adc_power_on();
|
||||
adc_power_always_on();
|
||||
}
|
||||
// configure I2S data port interface.
|
||||
i2s_reset_fifo(i2s_num);
|
||||
@ -1171,6 +1182,27 @@ esp_err_t i2s_write(i2s_port_t i2s_num, const void *src, size_t size, size_t *by
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_adc_enable(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
adc1_i2s_mode_acquire();
|
||||
_i2s_adc_mode_recover();
|
||||
return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
|
||||
}
|
||||
|
||||
esp_err_t i2s_adc_disable(i2s_port_t i2s_num)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num] != NULL), "Not initialized yet", ESP_ERR_INVALID_STATE);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num]->mode & I2S_MODE_ADC_BUILT_IN), "i2s built-in adc not enabled", ESP_ERR_INVALID_STATE);
|
||||
|
||||
adc1_lock_release();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, size_t src_bits, size_t aim_bits, size_t *bytes_written, TickType_t ticks_to_wait)
|
||||
{
|
||||
char *data_ptr;
|
||||
|
@ -204,12 +204,13 @@ int adc1_get_voltage(adc1_channel_t channel) __attribute__((deprecated));
|
||||
/** @endcond */
|
||||
|
||||
/**
|
||||
* @brief Power on SAR ADC
|
||||
* @brief Enable ADC power
|
||||
*/
|
||||
void adc_power_on();
|
||||
|
||||
/**
|
||||
* @brief Power off SAR ADC
|
||||
* This function will force power down for ADC
|
||||
*/
|
||||
void adc_power_off();
|
||||
|
||||
|
@ -353,6 +353,8 @@ int i2s_read_bytes(i2s_port_t i2s_num, void *dest, size_t size, TickType_t ticks
|
||||
*
|
||||
* @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process,
|
||||
* to prevent the data getting corrupted.
|
||||
* @note If the built-in ADC mode is enabled, we should call i2s_adc_start and i2s_adc_stop around the whole reading process,
|
||||
* to prevent the data getting corrupted.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
@ -485,6 +487,31 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
*/
|
||||
esp_err_t i2s_set_adc_mode(adc_unit_t adc_unit, adc1_channel_t adc_channel);
|
||||
|
||||
/**
|
||||
* @brief Start to use I2S built-in ADC mode
|
||||
* @note This function would acquire the lock of ADC to prevent the data getting corrupted
|
||||
* during the I2S peripheral is being used to do fully continuous ADC sampling.
|
||||
*
|
||||
* @param i2s_num i2s port index
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_INVALID_STATE driver state error
|
||||
* - ESP_FAIL Internal driver error
|
||||
*/
|
||||
esp_err_t i2s_adc_enable(i2s_port_t i2s_num);
|
||||
|
||||
/**
|
||||
* @brief Stop to use I2S built-in ADC mode
|
||||
* @param i2s_num i2s port index
|
||||
* @note This function would release the lock of ADC so that other tasks can use ADC.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
* - ESP_ERR_INVALID_STATE driver state error
|
||||
*/
|
||||
esp_err_t i2s_adc_disable(i2s_port_t i2s_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "sys/lock.h"
|
||||
#include "driver/rtc_cntl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "adc1_i2s_private.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Enable built-in checks in queue.h in debug builds
|
||||
@ -99,6 +100,9 @@ static _lock_t adc2_wifi_lock = NULL;
|
||||
//prevent ADC2 being used by tasks (regardless of WIFI)
|
||||
portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
//prevent ADC1 being used by I2S dma and other tasks at the same time.
|
||||
static _lock_t adc1_i2s_lock = NULL;
|
||||
|
||||
typedef struct {
|
||||
TimerHandle_t timer;
|
||||
uint32_t filtered_val[TOUCH_PAD_MAX];
|
||||
@ -108,12 +112,6 @@ typedef struct {
|
||||
} touch_pad_filter_t;
|
||||
static touch_pad_filter_t *s_touch_pad_filter = NULL;
|
||||
|
||||
typedef enum {
|
||||
ADC_FORCE_FSM = 0x0,
|
||||
ADC_FORCE_DISABLE = 0x2,
|
||||
ADC_FORCE_ENABLE = 0x3,
|
||||
} adc_force_mode_t;
|
||||
|
||||
//Reg,Mux,Fun,IE,Up,Down,Rtc_number
|
||||
const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
|
||||
{RTC_IO_TOUCH_PAD1_REG, RTC_IO_TOUCH_PAD1_MUX_SEL_M, RTC_IO_TOUCH_PAD1_FUN_SEL_S, RTC_IO_TOUCH_PAD1_FUN_IE_M, RTC_IO_TOUCH_PAD1_RUE_M, RTC_IO_TOUCH_PAD1_RDE_M, RTC_IO_TOUCH_PAD1_SLP_SEL_M, RTC_IO_TOUCH_PAD1_SLP_IE_M, RTC_IO_TOUCH_PAD1_HOLD_M, RTC_CNTL_TOUCH_PAD1_HOLD_FORCE_M, RTC_IO_TOUCH_PAD1_DRV_V, RTC_IO_TOUCH_PAD1_DRV_S, RTCIO_GPIO0_CHANNEL}, //0
|
||||
@ -1025,10 +1023,21 @@ static esp_err_t adc_set_atten(adc_unit_t adc_unit, adc_channel_t channel, adc_a
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void adc_power_always_on()
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
void adc_power_on()
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_FSM;
|
||||
if (SENS.sar_meas_wait2.force_xpd_sar & SENS_FORCE_XPD_SAR_SW_M) {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
} else {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
@ -1037,7 +1046,7 @@ void adc_power_off()
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Bit1 0:Fsm 1: SW mode
|
||||
//Bit0 0:SW mode power down 1: SW mode power on
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_DISABLE;
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
@ -1161,7 +1170,7 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
|
||||
uint8_t table_len = 1;
|
||||
//POWER ON SAR
|
||||
adc_power_on();
|
||||
adc_power_always_on();
|
||||
adc_gpio_init(adc_unit, channel);
|
||||
adc_set_i2s_data_len(adc_unit, table_len);
|
||||
adc_set_i2s_data_pattern(adc_unit, 0, channel, ADC_WIDTH_BIT_12, ADC_ATTEN_DB_11);
|
||||
@ -1246,12 +1255,55 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_i2s_mode_acquire()
|
||||
{
|
||||
//lazy initialization
|
||||
//for i2s, block until acquire the lock
|
||||
_lock_acquire( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "i2s mode takes adc1 lock." );
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
//switch SARADC into DIG channel
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 1;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_adc_mode_acquire()
|
||||
{
|
||||
//lazy initialization
|
||||
//for adc1, block until acquire the lock
|
||||
_lock_acquire( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "adc mode takes adc1 lock." );
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// for now the WiFi would use ADC2 and set xpd_sar force on.
|
||||
// so we can not reset xpd_sar to fsm mode directly.
|
||||
// We should handle this after the synchronization mechanism is established.
|
||||
|
||||
//switch SARADC into RTC channel
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 0;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_lock_release()
|
||||
{
|
||||
RTC_MODULE_CHECK((uint32_t*)adc1_i2s_lock != NULL, "adc1 lock release called before acquire", ESP_ERR_INVALID_STATE );
|
||||
// for now the WiFi would use ADC2 and set xpd_sar force on.
|
||||
// so we can not reset xpd_sar to fsm mode directly.
|
||||
// We should handle this after the synchronization mechanism is established.
|
||||
|
||||
_lock_release( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "returns adc1 lock." );
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
int adc1_get_raw(adc1_channel_t channel)
|
||||
{
|
||||
uint16_t adc_value;
|
||||
RTC_MODULE_CHECK(channel < ADC1_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
|
||||
adc_power_on();
|
||||
adc1_adc_mode_acquire();
|
||||
adc_power_on();
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Adc Controler is Rtc module,not ulp coprocessor
|
||||
@ -1274,6 +1326,7 @@ int adc1_get_raw(adc1_channel_t channel)
|
||||
while (SENS.sar_meas_start1.meas1_done_sar == 0);
|
||||
adc_value = SENS.sar_meas_start1.meas1_data_sar;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
adc1_lock_release();
|
||||
return adc_value;
|
||||
}
|
||||
|
||||
@ -1467,6 +1520,8 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
rtc_gpio_input_disable(gpio);
|
||||
rtc_gpio_pullup_dis(gpio);
|
||||
rtc_gpio_pulldown_dis(gpio);
|
||||
//force fsm
|
||||
adc_power_always_on(); //Select power source of ADC
|
||||
|
||||
RTCCNTL.bias_conf.dbg_atten = 0; //Check DBG effect outside sleep mode
|
||||
//set dtest (MUX_SEL : 0 -> RTC; 1-> vdd_sar2)
|
||||
@ -1475,8 +1530,6 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
RTCCNTL.test_mux.ent_rtc = 1;
|
||||
//set sar2_en_test
|
||||
SENS.sar_start_force.sar2_en_test = 1;
|
||||
//force fsm
|
||||
SENS.sar_meas_wait2.force_xpd_sar = ADC_FORCE_ENABLE; //Select power source of ADC
|
||||
//set sar2 en force
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
|
||||
//set en_pad for channels 7,8,9 (bits 0x380)
|
||||
|
@ -96,6 +96,7 @@
|
||||
#define SENS_FORCE_XPD_SAR_M ((SENS_FORCE_XPD_SAR_V)<<(SENS_FORCE_XPD_SAR_S))
|
||||
#define SENS_FORCE_XPD_SAR_V 0x3
|
||||
#define SENS_FORCE_XPD_SAR_S 18
|
||||
#define SENS_FORCE_XPD_SAR_SW_M (BIT1)
|
||||
#define SENS_FORCE_XPD_SAR_FSM 0 // Use FSM to control power down
|
||||
#define SENS_FORCE_XPD_SAR_PD 2 // Force power down
|
||||
#define SENS_FORCE_XPD_SAR_PU 3 // Force power up
|
||||
|
@ -9,8 +9,11 @@
|
||||
#include "driver/i2s.h"
|
||||
#include "driver/adc.h"
|
||||
#include "audio_example_file.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
static const char* TAG = "ad/da";
|
||||
#define V_REF 1100
|
||||
#define ADC1_TEST_CHANNEL (ADC1_CHANNEL_7)
|
||||
|
||||
#define PARTITION_NAME "storage"
|
||||
|
||||
@ -36,6 +39,10 @@ static const char* TAG = "ad/da";
|
||||
#define EXAMPLE_I2S_FORMAT (I2S_CHANNEL_FMT_RIGHT_LEFT)
|
||||
//I2S channel number
|
||||
#define EXAMPLE_I2S_CHANNEL_NUM ((EXAMPLE_I2S_FORMAT < I2S_CHANNEL_FMT_ONLY_RIGHT) ? (2) : (1))
|
||||
//I2S built-in ADC unit
|
||||
#define I2S_ADC_UNIT ADC_UNIT_1
|
||||
//I2S built-in ADC channel
|
||||
#define I2S_ADC_CHANNEL ADC1_CHANNEL_0
|
||||
|
||||
//flash record size, for recording 5 seconds' data
|
||||
#define FLASH_RECORD_SIZE (EXAMPLE_I2S_CHANNEL_NUM * EXAMPLE_I2S_SAMPLE_RATE * EXAMPLE_I2S_SAMPLE_BITS / 8 * 5)
|
||||
@ -45,6 +52,7 @@ static const char* TAG = "ad/da";
|
||||
//flash read / write address
|
||||
#define FLASH_ADDR (0x200000)
|
||||
|
||||
|
||||
/**
|
||||
* @brief I2S ADC/DAC mode init.
|
||||
*/
|
||||
@ -66,7 +74,7 @@ void example_i2s_init()
|
||||
//init DAC pad
|
||||
i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
|
||||
//init ADC pad
|
||||
i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_0);
|
||||
i2s_set_adc_mode(I2S_ADC_UNIT, I2S_ADC_CHANNEL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -193,10 +201,8 @@ void example_i2s_adc_dac(void*arg)
|
||||
ESP_LOGE(TAG, "Partition error: can't find partition name: %s\n", PARTITION_NAME);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
//1. Erase flash
|
||||
example_erase_flash();
|
||||
example_i2s_init();
|
||||
int i2s_read_len = EXAMPLE_I2S_READ_LEN;
|
||||
int flash_wr_size = 0;
|
||||
size_t bytes_read, bytes_written;
|
||||
@ -205,6 +211,7 @@ void example_i2s_adc_dac(void*arg)
|
||||
#if RECORD_IN_FLASH_EN
|
||||
char* i2s_read_buff = (char*) calloc(i2s_read_len, sizeof(char));
|
||||
uint8_t* flash_write_buff = (uint8_t*) calloc(i2s_read_len, sizeof(char));
|
||||
i2s_adc_enable(EXAMPLE_I2S_NUM);
|
||||
while (flash_wr_size < FLASH_RECORD_SIZE) {
|
||||
//read data from I2S bus, in this case, from ADC.
|
||||
i2s_read(EXAMPLE_I2S_NUM, i2s_read_buff, i2s_read_len, &bytes_read, portMAX_DELAY);
|
||||
@ -214,6 +221,7 @@ void example_i2s_adc_dac(void*arg)
|
||||
flash_wr_size += i2s_read_len;
|
||||
ets_printf("Sound recording %u%%\n", flash_wr_size * 100 / FLASH_RECORD_SIZE);
|
||||
}
|
||||
i2s_adc_disable(EXAMPLE_I2S_NUM);
|
||||
free(i2s_read_buff);
|
||||
i2s_read_buff = NULL;
|
||||
free(flash_write_buff);
|
||||
@ -257,10 +265,28 @@ void example_i2s_adc_dac(void*arg)
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void adc_read_task(void* arg)
|
||||
{
|
||||
adc1_config_width(ADC_WIDTH_12Bit);
|
||||
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_11db);
|
||||
esp_adc_cal_characteristics_t characteristics;
|
||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_11db, ADC_WIDTH_12Bit, ESP_ADC_CAL_VAL_DEFAULT_VREF, &characteristics);
|
||||
|
||||
while(1) {
|
||||
uint32_t voltage;
|
||||
esp_err_t ret = esp_adc_cal_get_voltage(ADC1_TEST_CHANNEL, &characteristics, &voltage);
|
||||
assert(ret==ESP_OK);
|
||||
ESP_LOGI(TAG, "%d mV", voltage);
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t app_main()
|
||||
{
|
||||
example_i2s_init();
|
||||
esp_log_level_set("I2S", ESP_LOG_INFO);
|
||||
xTaskCreate(example_i2s_adc_dac, "example_i2s_adc_dac", 1024 * 2, NULL, 5, NULL);
|
||||
xTaskCreate(adc_read_task, "ADC read task", 2048, NULL, 5, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user