Merge branch 'feature/dac_driver_hal_support' into 'master'

dac: add hal for dac driver

See merge request espressif/esp-idf!5591
This commit is contained in:
Wang Jia Lin 2019-11-22 13:59:32 +08:00
commit a8d3e3ab4a
21 changed files with 907 additions and 138 deletions

View File

@ -1,5 +1,6 @@
set(srcs
"can.c"
"dac.c"
"gpio.c"
"i2c.c"
"i2s.c"

154
components/driver/dac.c Normal file
View File

@ -0,0 +1,154 @@
// 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.
#include <string.h>
#include "esp_log.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/timers.h"
#include "driver/rtc_io.h"
#include "driver/dac.h"
#include "soc/dac_periph.h"
#include "hal/dac_hal.h"
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
static const char *DAC_TAG = "DAC";
#define DAC_CHECK(a, str, ret_val) ({ \
if (!(a)) { \
ESP_LOGE(DAC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
return (ret_val); \
} \
})
/*---------------------------------------------------------------
DAC
---------------------------------------------------------------*/
esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num)
{
DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG);
*gpio_num = (gpio_num_t)dac_periph_signal.dac_channel_io_num[channel];
return ESP_OK;
}
static esp_err_t dac_rtc_pad_init(dac_channel_t channel)
{
DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG);
gpio_num_t gpio_num = 0;
dac_pad_get_io_num(channel, &gpio_num);
rtc_gpio_init(gpio_num);
rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_pulldown_dis(gpio_num);
return ESP_OK;
}
esp_err_t dac_output_enable(dac_channel_t channel)
{
DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG);
dac_rtc_pad_init(channel);
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_power_on(channel);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_output_disable(dac_channel_t channel)
{
DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_power_down(channel);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value)
{
DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_update_output_value(channel, dac_value);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_out_voltage(dac_channel_t channel, uint8_t dac_value)
{
DAC_CHECK(channel < DAC_CHANNEL_MAX, "DAC channel error", ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_update_output_value(channel, dac_value);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_i2s_enable(void)
{
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_dma_enable();
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_i2s_disable(void)
{
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_dma_disable();
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_cw_generator_enable(void)
{
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_cw_generator_enable();
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_cw_generator_disable(void)
{
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_cw_generator_disable();
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_cw_generator_config(dac_cw_config_t *cw)
{
assert(cw != NULL);
portENTER_CRITICAL(&rtc_spinlock);
dac_hal_cw_generator_config(cw);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}

View File

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _DRIVER_DAC_H_
#define _DRIVER_DAC_H_
#pragma once
#ifdef __cplusplus
extern "C" {
@ -21,41 +20,30 @@ extern "C" {
#include <stdint.h>
#include "esp_err.h"
#include "soc/dac_periph.h"
typedef enum {
DAC_CHANNEL_1 = 1, /*!< DAC channel 1 is GPIO25 (ESP32), GPIO17 (ESP32-S2) */
DAC_CHANNEL_2, /*!< DAC channel 2 is GPIO26 (ESP32), GPIO18 (ESP32-S2) */
DAC_CHANNEL_MAX,
} dac_channel_t;
#include "driver/gpio.h"
#include "hal/dac_types.h"
/**
* @brief Get the gpio number of a specific DAC channel.
*
*
* @param channel Channel to get the gpio number
*
* @param gpio_num output buffer to hold the gpio number
*
* @return
* @return
* - ESP_OK if success
* - ESP_ERR_INVALID_ARG if channal not valid
*/
esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num);
/**
* @brief Set DAC output voltage.
*
* DAC output is 8-bit. Maximum (255) corresponds to VDD.
* DAC output is 8-bit. Maximum (255) corresponds to VDD3P3_RTC.
*
* @note Need to configure DAC pad before calling this function.
* DAC channel 1 is attached to GPIO25, DAC channel 2 is attached to GPIO26
*
* @param channel DAC channel
* @param dac_value DAC output value
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value);
@ -74,21 +62,53 @@ esp_err_t dac_output_enable(dac_channel_t channel);
*
* @param channel DAC channel
* @note DAC channel 1 is attached to GPIO25, DAC channel 2 is attached to GPIO26
* @return
* - ESP_OK success
*/
esp_err_t dac_output_disable(dac_channel_t channel);
/**
* @brief Enable DAC output data from I2S
*
* @return
* - ESP_OK success
*/
esp_err_t dac_i2s_enable(void);
/**
* @brief Disable DAC output data from I2S
*
* @return
* - ESP_OK success
*/
esp_err_t dac_i2s_disable(void);
/**
* @brief Enable cosine wave generator output.
*
* @return
* - ESP_OK success
*/
esp_err_t dac_cw_generator_enable(void);
/**
* @brief Disable cosine wave generator output.
*
* @return
* - ESP_OK success
*/
esp_err_t dac_cw_generator_disable(void);
/**
* @brief Config the cosine wave generator function in DAC module.
*
* @param cw Configuration.
* @return
* - ESP_OK success
*/
esp_err_t dac_cw_generator_config(dac_cw_config_t *cw);
#ifdef __cplusplus
}
#endif
#endif /*_DRIVER_DAC_H_*/

View File

@ -41,6 +41,7 @@
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
#include "hal/dac_hal.h"
#ifndef NDEBUG
// Enable built-in checks in queue.h in debug builds
@ -48,19 +49,17 @@
#endif
#include "sys/queue.h"
#define ADC_FSM_RSTB_WAIT_DEFAULT (8)
#define ADC_FSM_START_WAIT_DEFAULT (5)
#define ADC_FSM_STANDBY_WAIT_DEFAULT (100)
#define ADC_FSM_TIME_KEEP (-1)
#define ADC_MAX_MEAS_NUM_DEFAULT (255)
#define ADC_MEAS_NUM_LIM_DEFAULT (1)
#define SAR_ADC_CLK_DIV_DEFUALT (2)
#define SAR_ADC_CLK_DIV_DEFAULT (2)
#define ADC_PATT_LEN_MAX (16)
#define TOUCH_PAD_FILTER_FACTOR_DEFAULT (4) // IIR filter coefficient.
#define TOUCH_PAD_SHIFT_DEFAULT (4) // Increase computing accuracy.
#define TOUCH_PAD_SHIFT_ROUND_DEFAULT (8) // ROUND = 2^(n-1); rounding off for fractional.
#define DAC_ERR_STR_CHANNEL_ERROR "DAC channel error"
static const char *RTC_MODULE_TAG = "RTC_MODULE";
@ -136,7 +135,6 @@ typedef enum {
static const char TAG[] = "adc";
static inline void dac_output_set_enable(dac_channel_t channel, bool enable);
static inline void adc1_hall_enable(bool enable);
#if CONFIG_IDF_TARGET_ESP32
@ -973,7 +971,7 @@ void adc_power_off(void)
esp_err_t adc_set_clk_div(uint8_t clk_div)
{
portENTER_CRITICAL(&rtc_spinlock);
// ADC clock devided from APB clk, 80 / 2 = 40Mhz,
// ADC clock divided from APB clk, 80 / 2 = 40Mhz,
SYSCON.saradc_ctrl.sar_clk_div = clk_div;
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
@ -1298,7 +1296,7 @@ esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel)
}
portEXIT_CRITICAL(&rtc_spinlock);
adc_set_i2s_data_source(ADC_I2S_DATA_SRC_ADC);
adc_set_clk_div(SAR_ADC_CLK_DIV_DEFUALT);
adc_set_clk_div(SAR_ADC_CLK_DIV_DEFAULT);
// Set internal FSM wait time.
adc_set_fsm_time(ADC_FSM_RSTB_WAIT_DEFAULT, ADC_FSM_START_WAIT_DEFAULT, ADC_FSM_STANDBY_WAIT_DEFAULT,
ADC_FSM_TIME_KEEP);
@ -1602,15 +1600,15 @@ static inline void adc2_dac_disable( adc2_channel_t channel)
{
#if CONFIG_IDF_TARGET_ESP32
if ( channel == ADC2_CHANNEL_8 ) { // the same as DAC channel 1
dac_output_set_enable( DAC_CHANNEL_1, false );
dac_ll_power_down( DAC_CHANNEL_1 );
} else if ( channel == ADC2_CHANNEL_9 ) {
dac_output_set_enable( DAC_CHANNEL_2, false );
dac_ll_power_down( DAC_CHANNEL_2 );
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if ( channel == ADC2_CHANNEL_6 ) { // the same as DAC channel 1
dac_output_set_enable( DAC_CHANNEL_1, false );
dac_ll_power_down( DAC_CHANNEL_1 );
} else if ( channel == ADC2_CHANNEL_7 ) {
dac_output_set_enable( DAC_CHANNEL_2, false );
dac_ll_power_down( DAC_CHANNEL_2 );
}
#endif
}
@ -1689,110 +1687,6 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
return ESP_OK;
}
/*---------------------------------------------------------------
DAC
---------------------------------------------------------------*/
esp_err_t dac_pad_get_io_num(dac_channel_t channel, gpio_num_t *gpio_num)
{
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
RTC_MODULE_CHECK(gpio_num, "Param null", ESP_ERR_INVALID_ARG);
switch (channel) {
case DAC_CHANNEL_1:
*gpio_num = DAC_CHANNEL_1_GPIO_NUM;
break;
case DAC_CHANNEL_2:
*gpio_num = DAC_CHANNEL_2_GPIO_NUM;
break;
default:
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}
static esp_err_t dac_rtc_pad_init(dac_channel_t channel)
{
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
gpio_num_t gpio_num = 0;
dac_pad_get_io_num(channel, &gpio_num);
rtc_gpio_init(gpio_num);
rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_pulldown_dis(gpio_num);
return ESP_OK;
}
static inline void dac_output_set_enable(dac_channel_t channel, bool enable)
{
RTCIO.pad_dac[channel-DAC_CHANNEL_1].dac_xpd_force = enable;
RTCIO.pad_dac[channel-DAC_CHANNEL_1].xpd_dac = enable;
}
esp_err_t dac_output_enable(dac_channel_t channel)
{
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
dac_rtc_pad_init(channel);
portENTER_CRITICAL(&rtc_spinlock);
dac_output_set_enable(channel, true);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_output_disable(dac_channel_t channel)
{
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&rtc_spinlock);
dac_output_set_enable(channel, false);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_output_voltage(dac_channel_t channel, uint8_t dac_value)
{
RTC_MODULE_CHECK((channel >= DAC_CHANNEL_1) && (channel < DAC_CHANNEL_MAX), DAC_ERR_STR_CHANNEL_ERROR, ESP_ERR_INVALID_ARG);
portENTER_CRITICAL(&rtc_spinlock);
//Disable Tone
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_SW_TONE_EN);
//Disable Channel Tone
if (channel == DAC_CHANNEL_1) {
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN1_M);
} else if (channel == DAC_CHANNEL_2) {
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL2_REG, SENS_DAC_CW_EN2_M);
}
//Set the Dac value
if (channel == DAC_CHANNEL_1) {
SET_PERI_REG_BITS(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_DAC, dac_value, RTC_IO_PDAC1_DAC_S); //dac_output
} else if (channel == DAC_CHANNEL_2) {
SET_PERI_REG_BITS(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_DAC, dac_value, RTC_IO_PDAC2_DAC_S); //dac_output
}
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_i2s_enable(void)
{
portENTER_CRITICAL(&rtc_spinlock);
SET_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_DAC_DIG_FORCE_M | SENS_DAC_CLK_INV_M);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
esp_err_t dac_i2s_disable(void)
{
portENTER_CRITICAL(&rtc_spinlock);
CLEAR_PERI_REG_MASK(SENS_SAR_DAC_CTRL1_REG, SENS_DAC_DIG_FORCE_M | SENS_DAC_CLK_INV_M);
portEXIT_CRITICAL(&rtc_spinlock);
return ESP_OK;
}
/*---------------------------------------------------------------
HALL SENSOR
---------------------------------------------------------------*/

View File

@ -14,6 +14,7 @@ list(APPEND srcs
"src/lldesc.c"
"src/hal/rmt_hal.c"
"src/hal/rtc_io_hal.c"
"src/hal/dac_hal.c"
"src/hal/spi_hal.c"
"src/hal/spi_hal_iram.c"
"src/hal/spi_slave_hal.c"

View File

@ -0,0 +1,23 @@
// 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.
#include "soc/dac_periph.h"
/*
Bunch of constants for DAC peripheral: GPIO number
*/
const dac_signal_conn_t dac_periph_signal = {
.dac_channel_io_num[0] = DAC_CHANNEL_1_GPIO_NUM,
.dac_channel_io_num[1] = DAC_CHANNEL_2_GPIO_NUM,
};

View File

@ -0,0 +1,185 @@
// 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.
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
#pragma once
#include <stdlib.h>
#include "soc/dac_periph.h"
#include "hal/dac_types.h"
/**
* Power on dac module and start output voltage.
*
* @note Before powering up, make sure the DAC PAD is set to RTC PAD and floating status.
* @param channel DAC channel num.
*/
static inline void dac_ll_power_on(dac_channel_t channel)
{
RTCIO.pad_dac[channel].dac_xpd_force = 1;
RTCIO.pad_dac[channel].xpd_dac = 1;
}
/**
* Power done dac module and stop output voltage.
*
* @param channel DAC channel num.
*/
static inline void dac_ll_power_down(dac_channel_t channel)
{
RTCIO.pad_dac[channel].dac_xpd_force = 0;
RTCIO.pad_dac[channel].xpd_dac = 0;
}
/**
* Output voltage with value (8 bit).
*
* @param channel DAC channel num.
* @param value Output value. Value range: 0 ~ 255.
* The corresponding range of voltage is 0v ~ VDD3P3_RTC.
*/
static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t value)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_cw_en1 = 0;
RTCIO.pad_dac[channel].dac = value;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_cw_en2 = 0;
RTCIO.pad_dac[channel].dac = value;
}
}
/************************************/
/* DAC cosine wave generator API's */
/************************************/
/**
* Enable cosine wave generator output.
*/
static inline void dac_ll_cw_generator_enable(void)
{
SENS.sar_dac_ctrl1.sw_tone_en = 1;
}
/**
* Disable cosine wave generator output.
*/
static inline void dac_ll_cw_generator_disable(void)
{
SENS.sar_dac_ctrl1.sw_tone_en = 0;
}
/**
* Enable the cosine wave generator of DAC channel.
*
* @param channel DAC channel num.
* @param enable
*/
static inline void dac_ll_cw_set_channel(dac_channel_t channel, bool enable)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_cw_en1 = enable;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_cw_en2 = enable;
}
}
/**
* Set frequency of cosine wave generator output.
*
* @note We know that CLK8M is about 8M, but don't know the actual value. so this freq have limited error.
* @param freq_hz CW generator frequency. Range: 130(130Hz) ~ 55000(100KHz).
*/
static inline void dac_ll_cw_set_freq(uint32_t freq)
{
uint32_t sw_freq = freq * 0xFFFF / RTC_FAST_CLK_FREQ_APPROX;
SENS.sar_dac_ctrl1.sw_fstep = (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq;
}
/**
* Set the amplitude of the cosine wave generator output.
*
* @param channel DAC channel num.
* @param scale The multiple of the amplitude. The max amplitude is VDD3P3_RTC.
*/
static inline void dac_ll_cw_set_scale(dac_channel_t channel, dac_cw_scale_t scale)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_scale1 = scale;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_scale2 = scale;
}
}
/**
* Set the phase of the cosine wave generator output.
*
* @param channel DAC channel num.
* @param scale Phase value.
*/
static inline void dac_ll_cw_set_phase(dac_channel_t channel, dac_cw_phase_t phase)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_inv1 = phase;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_inv2 = phase;
}
}
/**
* Set the voltage value of the DC component of the cosine wave generator output.
*
* @note The DC offset setting should be after phase setting.
* @note Unreasonable settings can cause the signal to be oversaturated.
* @param channel DAC channel num.
* @param offset DC value. Range: -128 ~ 127.
*/
static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset)
{
if (channel == DAC_CHANNEL_1) {
if (SENS.sar_dac_ctrl2.dac_inv1 == DAC_CW_PHASE_180) {
offset = 0 - offset;
}
SENS.sar_dac_ctrl2.dac_dc1 = offset ? offset : (-128 - offset);
} else if (channel == DAC_CHANNEL_2) {
if (SENS.sar_dac_ctrl2.dac_inv2 == DAC_CW_PHASE_180) {
offset = 0 - offset;
}
SENS.sar_dac_ctrl2.dac_dc2 = offset ? offset : (-128 - offset);
}
}
/************************************/
/* DAC DMA API's */
/************************************/
/**
* Enable DAC output data from I2S DMA.
* I2S_CLK connect to DAC_CLK, I2S_DATA_OUT connect to DAC_DATA.
*/
static inline void dac_ll_dma_enable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 1;
}
/**
* Disable DAC output data from I2S DMA.
*/
static inline void dac_ll_dma_disable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 0;
}

View File

@ -0,0 +1,22 @@
// 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.
#ifndef _SOC_RTC_DAC_CAPS_H_
#define _SOC_RTC_DAC_CAPS_H_
#define SOC_DAC_PERIPH_NUM 2
#define SOC_DAC_RESOLUTION 8 // DAC resolution ratio 8 bit
#endif

View File

@ -1,4 +1,5 @@
set(SOC_SRCS "cpu_util.c"
"dac_periph.c"
"gpio_periph.c"
"rtc_clk.c"
"rtc_clk_init.c"

View File

@ -0,0 +1,23 @@
// 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.
#include "soc/dac_periph.h"
/*
Bunch of constants for DAC peripheral: GPIO number
*/
const dac_signal_conn_t dac_periph_signal = {
.dac_channel_io_num[0] = DAC_CHANNEL_1_GPIO_NUM,
.dac_channel_io_num[1] = DAC_CHANNEL_2_GPIO_NUM,
};

View File

@ -0,0 +1,185 @@
// 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.
/*******************************************************************************
* NOTICE
* The ll is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
#pragma once
#include <stdlib.h>
#include "soc/dac_periph.h"
#include "hal/dac_types.h"
/**
* Power on dac module and start output voltage.
*
* @note Before powering up, make sure the DAC PAD is set to RTC PAD and floating status.
* @param channel DAC channel num.
*/
static inline void dac_ll_power_on(dac_channel_t channel)
{
RTCIO.pad_dac[channel].dac_xpd_force = 1;
RTCIO.pad_dac[channel].xpd_dac = 1;
}
/**
* Power done dac module and stop output voltage.
*
* @param channel DAC channel num.
*/
static inline void dac_ll_power_down(dac_channel_t channel)
{
RTCIO.pad_dac[channel].dac_xpd_force = 0;
RTCIO.pad_dac[channel].xpd_dac = 0;
}
/**
* Output voltage with value (8 bit).
*
* @param channel DAC channel num.
* @param value Output value. Value range: 0 ~ 255.
* The corresponding range of voltage is 0v ~ VDD3P3_RTC.
*/
static inline void dac_ll_update_output_value(dac_channel_t channel, uint8_t value)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_cw_en1 = 0;
RTCIO.pad_dac[channel].dac = value;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_cw_en2 = 0;
RTCIO.pad_dac[channel].dac = value;
}
}
/************************************/
/* DAC cosine wave generator API's */
/************************************/
/**
* Enable cosine wave generator output.
*/
static inline void dac_ll_cw_generator_enable(void)
{
SENS.sar_dac_ctrl1.sw_tone_en = 1;
}
/**
* Disable cosine wave generator output.
*/
static inline void dac_ll_cw_generator_disable(void)
{
SENS.sar_dac_ctrl1.sw_tone_en = 0;
}
/**
* Enable the cosine wave generator of DAC channel.
*
* @param channel DAC channel num.
* @param enable
*/
static inline void dac_ll_cw_set_channel(dac_channel_t channel, bool enable)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_cw_en1 = enable;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_cw_en2 = enable;
}
}
/**
* Set frequency of cosine wave generator output.
*
* @note We know that CLK8M is about 8M, but don't know the actual value. so this freq have limited error.
* @param freq_hz CW generator frequency. Range: 130(130Hz) ~ 55000(100KHz).
*/
static inline void dac_ll_cw_set_freq(uint32_t freq)
{
uint32_t sw_freq = freq * 0xFFFF / RTC_FAST_CLK_FREQ_APPROX;
SENS.sar_dac_ctrl1.sw_fstep = (sw_freq > 0xFFFF) ? 0xFFFF : sw_freq;
}
/**
* Set the amplitude of the cosine wave generator output.
*
* @param channel DAC channel num.
* @param scale The multiple of the amplitude. The max amplitude is VDD3P3_RTC.
*/
static inline void dac_ll_cw_set_scale(dac_channel_t channel, dac_cw_scale_t scale)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_scale1 = scale;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_scale2 = scale;
}
}
/**
* Set the phase of the cosine wave generator output.
*
* @param channel DAC channel num.
* @param scale Phase value.
*/
static inline void dac_ll_cw_set_phase(dac_channel_t channel, dac_cw_phase_t phase)
{
if (channel == DAC_CHANNEL_1) {
SENS.sar_dac_ctrl2.dac_inv1 = phase;
} else if (channel == DAC_CHANNEL_2) {
SENS.sar_dac_ctrl2.dac_inv2 = phase;
}
}
/**
* Set the voltage value of the DC component of the cosine wave generator output.
*
* @note The DC offset setting should be after phase setting.
* @note Unreasonable settings can cause the signal to be oversaturated.
* @param channel DAC channel num.
* @param offset DC value. Range: -128 ~ 127.
*/
static inline void dac_ll_cw_set_dc_offset(dac_channel_t channel, int8_t offset)
{
if (channel == DAC_CHANNEL_1) {
if (SENS.sar_dac_ctrl2.dac_inv1 == DAC_CW_PHASE_180) {
offset = 0 - offset;
}
SENS.sar_dac_ctrl2.dac_dc1 = offset ? offset : (-128 - offset);
} else if (channel == DAC_CHANNEL_2) {
if (SENS.sar_dac_ctrl2.dac_inv2 == DAC_CW_PHASE_180) {
offset = 0 - offset;
}
SENS.sar_dac_ctrl2.dac_dc2 = offset ? offset : (-128 - offset);
}
}
/************************************/
/* DAC DMA API's */
/************************************/
/**
* Enable DAC output data from I2S DMA.
* I2S_CLK connect to DAC_CLK, I2S_DATA_OUT connect to DAC_DATA.
*/
static inline void dac_ll_dma_enable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 1;
}
/**
* Disable DAC output data from I2S DMA.
*/
static inline void dac_ll_dma_disable(void)
{
SENS.sar_dac_ctrl1.dac_dig_force = 0;
}

View File

@ -0,0 +1,22 @@
// 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.
#ifndef _SOC_RTC_DAC_CAPS_H_
#define _SOC_RTC_DAC_CAPS_H_
#define SOC_DAC_PERIPH_NUM 2
#define SOC_DAC_RESOLUTION 8 // DAC resolution ratio 8 bit
#endif

View File

@ -1,4 +1,5 @@
set(SOC_SRCS "cpu_util.c"
"dac_periph.c"
"gpio_periph.c"
"rtc_clk.c"
"rtc_init.c"

View File

@ -0,0 +1,76 @@
// 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.
/*******************************************************************************
* NOTICE
* The hal is not public api, don't use in application code.
* See readme.md in soc/include/hal/readme.md
******************************************************************************/
#pragma once
#include "hal/dac_ll.h"
#include "hal/hal_defs.h"
#include <esp_err.h>
/**
* Power on dac module and start output voltage.
*
* @note Before powering up, make sure the DAC PAD is set to RTC PAD and floating status.
* @param channel DAC channel num.
*/
#define dac_hal_power_on(channel) dac_ll_power_on(channel)
/**
* Power done dac module and stop output voltage.
*
* @param channel DAC channel num.
*/
#define dac_hal_power_down(channel) dac_ll_power_down(channel)
/**
* Output voltage with value (8 bit).
*
* @param channel DAC channel num.
* @param value Output value. Value range: 0 ~ 255.
* The corresponding range of voltage is 0v ~ VDD3P3_RTC.
*/
#define dac_hal_update_output_value(channel, value) dac_ll_update_output_value(channel, value)
/**
* Enable cosine wave generator output.
*/
#define dac_hal_cw_generator_enable() dac_ll_cw_generator_enable()
/**
* Disable cosine wave generator output.
*/
#define dac_hal_cw_generator_disable() dac_ll_cw_generator_disable()
/**
* Config the cosine wave generator function in DAC module.
*
* @param cw Configuration.
*/
void dac_hal_cw_generator_config(dac_cw_config_t *cw);
/**
* Enable DAC output data from DMA.
*/
#define dac_hal_dma_enable() dac_ll_dma_enable()
/**
* Disable DAC output data from DMA.
*/
#define dac_hal_dma_disable() dac_ll_dma_disable()

View File

@ -0,0 +1,40 @@
#pragma once
#include "soc/dac_caps.h"
#include "sdkconfig.h"
typedef enum {
DAC_CHANNEL_1 = 0, /*!< DAC channel 1 is GPIO25(ESP32) / GPIO17(ESP32S2BETA) */
DAC_CHANNEL_2 = 1, /*!< DAC channel 2 is GPIO26(ESP32) / GPIO18(ESP32S2BETA) */
DAC_CHANNEL_MAX,
} dac_channel_t;
/**
* The multiple of the amplitude of the cosine wave generator. The max amplitude is VDD3P3_RTC.
*/
typedef enum {
DAC_CW_SCALE_1 = 0x0, /*!< 1/1. Default. */
DAC_CW_SCALE_2 = 0x1, /*!< 1/2. */
DAC_CW_SCALE_4 = 0x2, /*!< 1/4. */
DAC_CW_SCALE_8 = 0x3, /*!< 1/8. */
} dac_cw_scale_t;
/**
* Set the phase of the cosine wave generator output.
*/
typedef enum {
DAC_CW_PHASE_0 = 0x2, /*!< Phase shift +0° */
DAC_CW_PHASE_180 = 0x3, /*!< Phase shift +180° */
} dac_cw_phase_t;
/**
* Config the cosine wave generator function in DAC module.
*/
typedef struct {
dac_channel_t en_ch; /*!< Enable the cosine wave generator of DAC channel. */
dac_cw_scale_t scale; /*!< Set the amplitude of the cosine wave generator output. */
dac_cw_phase_t phase; /*!< Set the phase of the cosine wave generator output. */
uint32_t freq; /*!< Set frequency of cosine wave generator output. Range: 130(130Hz) ~ 55000(100KHz). */
int8_t offset; /*!< Set the voltage value of the DC component of the cosine wave generator output.
Note: Unreasonable settings can cause waveform to be oversaturated. Range: -128 ~ 127. */
} dac_cw_config_t;

View File

@ -13,4 +13,26 @@
// limitations under the License.
#pragma once
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#include "soc/rtc_io_reg.h"
#include "soc/rtc_io_struct.h"
#include "soc/rtc.h"
#include "soc/dac_channel.h"
#include "soc/dac_caps.h"
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct {
const uint8_t dac_channel_io_num[SOC_DAC_PERIPH_NUM];
} dac_signal_conn_t;
extern const dac_signal_conn_t dac_periph_signal;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,24 @@
// 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.
#include "hal/dac_hal.h"
void dac_hal_cw_generator_config(dac_cw_config_t *cw)
{
dac_ll_cw_set_freq(cw->freq);
dac_ll_cw_set_scale(cw->en_ch, cw->scale);
dac_ll_cw_set_phase(cw->en_ch, cw->phase);
dac_ll_cw_set_dc_offset(cw->en_ch, cw->offset);
dac_ll_cw_set_channel(cw->en_ch, true);
}

View File

@ -112,6 +112,7 @@ INPUT = \
../../components/soc/include/hal/timer_types.h \
../../components/soc/include/hal/ledc_types.h \
../../components/soc/include/hal/i2c_types.h \
../../components/soc/include/hal/dac_types.h \
../../components/soc/esp32/include/soc/adc_channel.h \
../../components/soc/esp32/include/soc/dac_channel.h \
../../components/soc/esp32/include/soc/touch_channel.h \

View File

@ -8,11 +8,20 @@ In this example, we use ADC2 to measure the output of DAC.
### Hardware Required
#### ESP32 platform
* A development board with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
* A USB cable for power supply and programming
We use ADC1_CHANNEL_7 (GPIO27) and DAC_CHANNEL_1 (GPIO25) by default, you need to short the two GPIOs (if you have changed the ADC2 and DAC channel, please refer to Chapter 4.11 of the `ESP32 Technical Reference Manual` to get the pin number).
#### ESP32-S2 platform
* A development board with ESP32S2BETA SoC
* A USB cable for power supply and programming
We use ADC1_CHANNEL_7 (GPIO18) and DAC_CHANNEL_1 (GPIO17) by default, you need to short the two GPIOs (if you have changed the ADC2 and DAC channel, please refer to the `ESP32S2 Technical Reference Manual` to get the pin number).
### Configure the project
```
@ -38,6 +47,8 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui
Running this example, you will see the following log output on the serial monitor:
### ESP32 platform
```
ADC channel 7 @ GPIO 27, DAC channel 1 @ GPIO 25.
adc2_init...
@ -55,6 +66,25 @@ start conversion.
...
```
#### ESP32-S2 platform
```
ADC channel 7 @ GPIO 18, DAC channel 1 @ GPIO 17.
adc2_init...
start conversion.
1: 150
2: 203
3: 250
4: 300
5: 351
6: 400
7: 441
8: 491
9: 547
10: 595
...
```
## Troubleshooting
* program upload failure

View File

@ -2,6 +2,7 @@ menu "Example Configuration"
choice EXAMPLE_ADC2_CHANNEL
bool "ADC2 Channel Num"
depends on IDF_TARGET_ESP32
default EXAMPLE_ADC2_CHANNEL_7
help
The channel of ADC2 used in this example.
@ -28,6 +29,35 @@ menu "Example Configuration"
bool "ADC2 Channel 9 (GPIO 26)"
endchoice
choice EXAMPLE_ADC2_CHANNEL
bool "ADC2 Channel Num"
depends on IDF_TARGET_ESP32S2BETA
default EXAMPLE_ADC2_CHANNEL_7
help
The channel of ADC2 used in this example.
config EXAMPLE_ADC2_CHANNEL_0
bool "ADC2 Channel 0 (GPIO 11)"
config EXAMPLE_ADC2_CHANNEL_1
bool "ADC2 Channel 1 (GPIO 12)"
config EXAMPLE_ADC2_CHANNEL_2
bool "ADC2 Channel 2 (GPIO 13)"
config EXAMPLE_ADC2_CHANNEL_3
bool "ADC2 Channel 3 (GPIO 14)"
config EXAMPLE_ADC2_CHANNEL_4
bool "ADC2 Channel 4 (GPIO 15)"
config EXAMPLE_ADC2_CHANNEL_5
bool "ADC2 Channel 5 (GPIO 16)"
config EXAMPLE_ADC2_CHANNEL_6
bool "ADC2 Channel 6 (GPIO 17)"
config EXAMPLE_ADC2_CHANNEL_7
bool "ADC2 Channel 7 (GPIO 18)"
config EXAMPLE_ADC2_CHANNEL_8
bool "ADC2 Channel 8 (GPIO 19)"
config EXAMPLE_ADC2_CHANNEL_9
bool "ADC2 Channel 9 (GPIO 20)"
endchoice
config EXAMPLE_ADC2_CHANNEL
int
default 0 if EXAMPLE_ADC2_CHANNEL_0
@ -43,6 +73,7 @@ menu "Example Configuration"
choice EXAMPLE_DAC_CHANNEL
bool "DAC Channel Num"
depends on IDF_TARGET_ESP32
default EXAMPLE_DAC_CHANNEL_1
help
The channel of DAC used in this example.
@ -53,9 +84,22 @@ menu "Example Configuration"
bool "DAC Channel 2 (GPIO26)"
endchoice
choice EXAMPLE_DAC_CHANNEL
bool "DAC Channel Num"
depends on IDF_TARGET_ESP32S2BETA
default EXAMPLE_DAC_CHANNEL_1
help
The channel of DAC used in this example.
config EXAMPLE_DAC_CHANNEL_1
bool "DAC Channel 1 (GPIO17)"
config EXAMPLE_DAC_CHANNEL_2
bool "DAC Channel 2 (GPIO18)"
endchoice
config EXAMPLE_DAC_CHANNEL
int
default 1 if EXAMPLE_DAC_CHANNEL_1
default 2 if EXAMPLE_DAC_CHANNEL_2
default 0 if EXAMPLE_DAC_CHANNEL_1
default 1 if EXAMPLE_DAC_CHANNEL_2
endmenu

View File

@ -32,8 +32,8 @@ void app_main(void)
r = dac_pad_get_io_num( DAC_EXAMPLE_CHANNEL, &dac_gpio_num );
assert( r == ESP_OK );
printf("ADC channel %d @ GPIO %d, DAC channel %d @ GPIO %d.\n", ADC2_EXAMPLE_CHANNEL, adc_gpio_num,
DAC_EXAMPLE_CHANNEL, dac_gpio_num );
printf("ADC2 channel %d @ GPIO %d, DAC channel %d @ GPIO %d.\n", ADC2_EXAMPLE_CHANNEL, adc_gpio_num,
DAC_EXAMPLE_CHANNEL + 1, dac_gpio_num );
dac_output_enable( DAC_EXAMPLE_CHANNEL );