I'm trying to set a digital filter using the adc and dac at the same time, but I can't manage to initialize my dac since the I2S controller 0 is being used by the adc. Is there a way to switch between them? There's not much information about the usage of the dac and adc continuous library.
#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_adc/adc_continuous.h"
#include <string.h>
#include <freertos/semphr.h>
#include <stdlib.h>
#include <driver/dac_continuous.h>
#define DEBUG_PIN GPIO_NUM_2
#define ADC_CHANNEL ADC_CHANNEL_5
#define SIGNAL_SAMPLE_FREQUENCY 44100
#define SAMPLE_SIZE 64
adc_continuous_handle_t adc_handle = NULL;
dac_continuous_handle_t dac_handle = NULL;
static SemaphoreHandle_t frame_ready;
static const char *TAG = "EXAMPLE";
#define EXAMPLE_ADC_GET_CHANNEL(p_data) ((p_data)->type1.channel)
#define EXAMPLE_ADC_GET_DATA(p_data) ((p_data)->type1.data)
void gpio_init(void);
void blink_led(void);
void adc_init(void);
void dac_init(void);
bool IRAM_ATTR Convertion_Task(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data);
static void dac_write_data_synchronously(uint8_t *data, size_t data_size);
void app_main(void) {
gpio_init();
adc_init();
dac_init();
adc_continuous_start(adc_handle);
esp_err_t ret;
uint32_t ret_num = 0;
uint8_t result[SAMPLE_SIZE] = {0};
memset(result, 0xcc, SAMPLE_SIZE);
frame_ready = xSemaphoreCreateBinary();
while (1)
{
if (xSemaphoreTake(frame_ready, portMAX_DELAY) == pdTRUE){
while (1) {
ret = adc_continuous_read(adc_handle, result, SAMPLE_SIZE, &ret_num, 0);
if (ret == ESP_OK) {
for (int i = 0; i < ret_num; i += SOC_ADC_DIGI_RESULT_BYTES) {
adc_digi_output_data_t *p = (adc_digi_output_data_t*)&result[i];
uint32_t data = EXAMPLE_ADC_GET_DATA(p);
uint8_t data_8bit = (uint8_t)(data >> 4);
size_t data_8bit_size = sizeof(data_8bit);
adc_continuous_stop(adc_handle);
dac_write_data_synchronously(&data_8bit, data_8bit_size);
adc_continuous_start(adc_handle);
}
} else if (ret == ESP_ERR_TIMEOUT) {
break;
}
}
}
}
adc_continuous_stop(adc_handle);
adc_continuous_deinit(adc_handle);
vSemaphoreDelete(frame_ready);
}
void adc_init(void){
adc_continuous_handle_cfg_t adc_handle_config = {
.max_store_buf_size = 1024, // Buffer size
.conv_frame_size = SAMPLE_SIZE // Conversion frame size SOC_ADC_DIGI_DATA_BYTES_PER_CONV, in bytes
};
adc_digi_pattern_config_t adc_pattern = {
.atten = ADC_ATTEN_DB_11, // The input voltage of ADC will be attenuated extending the range
// of measurement by about 6 dB (2x)
.channel = ADC_CHANNEL, // Channel these configurations are refering to
.unit = ADC_UNIT_1, // Uses SAR ADC unit 2
.bit_width = ADC_BITWIDTH_12, // Default ADC output bits, max supported width will be selected
};
adc_continuous_config_t adc_config = {
.pattern_num = 1, // Number of ADC pin being read
.adc_pattern = &adc_pattern, // List of configurations for every ADC pin
.sample_freq_hz = SIGNAL_SAMPLE_FREQUENCY, // The expected ADC sampling frequency in Hz for audio capture
.conv_mode = ADC_CONV_SINGLE_UNIT_1, // Use ADC2 for conversion simultaneously
.format = ADC_DIGI_OUTPUT_FORMAT_TYPE1 // 12 Bit Resolution
};
adc_continuous_evt_cbs_t event_callback = {
.on_conv_done = Convertion_Task
};
adc_continuous_new_handle(&adc_handle_config, &adc_handle); // Initialize ADC continuous driver and get a handle to it
adc_continuous_config(adc_handle, &adc_config); // Set ADC continuous mode required configurations
adc_continuous_register_event_callbacks(adc_handle, &event_callback, NULL); // Register the callbacks
}
void gpio_init(void){
const gpio_config_t debug_config = {
.pin_bit_mask = (1ULL << DEBUG_PIN),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&debug_config);
}
void blink_led(void) {
gpio_set_level(DEBUG_PIN, 1);
vTaskDelay(100 / portTICK_PERIOD_MS); // Blink for 100 ms
gpio_set_level(DEBUG_PIN, 0);
}
bool Convertion_Task(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data){
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(frame_ready, &xHigherPriorityTaskWoken);
return (xHigherPriorityTaskWoken == pdTRUE);
}
void dac_init(void){
dac_continuous_config_t dac_config = {
.chan_mask = DAC_CHANNEL_MASK_CH0, // DAC channels' mask for selecting GPIO25 on ESP32
.desc_num = 4, // Typically, suggest setting the number bigger than 5, in case the DMA stopped while sending a short buffer
.buf_size = 2048, // Buffer size
.freq_hz = SIGNAL_SAMPLE_FREQUENCY, // The expected DAC conversion frequency in Hz for audio capture
.offset = 0, // Possible offset for the DAC digital data. Range -128~127
.clk_src = DAC_DIGI_CLK_SRC_APLL, // The default clock source of the digital controller: From 19.6 KHz to several MHz.
.chan_mode = DAC_CHANNEL_MODE_SIMUL, // The data in the DMA buffer is simultaneously output to the enable channel of the DAC.
};
dac_continuous_new_channels(&dac_config, &dac_handle);
dac_continuous_enable(dac_handle);
dac_continuous_handle_t dac_handle_temp = NULL;
esp_err_t init_result = dac_continuous_new_channels(&dac_config, &dac_handle_temp);
if (init_result == ESP_OK && dac_handle_temp != NULL) {
// Initialization successful, update the global handle
dac_handle = dac_handle_temp;
// Enable DAC
dac_continuous_enable(dac_handle);
} else {
ESP_LOGI(TAG, "DAC Initialization Error: %s", esp_err_to_name(init_result));
}
}
static void dac_write_data_synchronously(uint8_t *data, size_t data_size)
{
while (1) {
dac_continuous_write(dac_handle, data, data_size, NULL, -1);
vTaskDelay(pdMS_TO_TICKS(10));
}
}
I tried multiple logic structures to stop and restart the adc during dac usage but I've not been successful