I am building a bluetooth speaker that detects voice commands via microphone (using ESP32). The microphone is using I2S and an internal ADC. Then I have an external DAC to play music from bluetooth. i2s_num_0 is attached to the internal ADC. How do I connect i2s_num_1 to the external DAC? I tried replacing i2s_num_0 with i2s_num_1 in the following code, but it didn't work.
#include <Arduino.h>
#include <WiFi.h>
#include <driver/i2s.h>
#include <esp_task_wdt.h>
#include "I2SMicSampler.h"
#include "ADCSampler.h"
#include "config.h"
#include "CommandDetector.h"
#include "CommandProcessor.h"
// BT, config, discover, audio
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_bt_api.h"
#include "esp_a2dp_api.h"
// audio DAC and amp config
#include "driver/i2s.h"
// callback (processes bt data)
void bt_data_cb(const uint8_t *data, uint32_t len){
// number of 16 bit samples
int n = len/2;
// point to a 16bit sample
int16_t* data16=(int16_t*)data;
// create a variable (potentially processed) that we'll pass via I2S
int16_t fy;
// Records number of bytes written via I2S
size_t i2s_bytes_write = 0;
for(int i=0;i<n;i++){
// put the current sample in fy
fy=*data16;
//making this value larger will decrease the volume(Very simple DSP!).
fy/=1;
// write data to I2S buffer
i2s_write(I2S_NUM_1, &fy, 2, &i2s_bytes_write, 10 );
//move to next memory address housing 16 bit data
data16++;
}
}
// i2s config for using the internal ADC
i2s_config_t adcI2SConfig = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_LSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0};
// i2s config for using BT
i2s_config_t i2s_config = {
.mode = static_cast<i2s_mode_t>(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = 44100,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = static_cast<i2s_comm_format_t>(I2S_COMM_FORMAT_I2S|I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // default interrupt priority
.dma_buf_count = 8,
.dma_buf_len = 1000,
.use_apll = false,
.tx_desc_auto_clear = true
};
// This task does all the heavy lifting for our application
void applicationTask(void *param)
{
CommandDetector *commandDetector = static_cast<CommandDetector *>(param);
const TickType_t xMaxBlockTime = pdMS_TO_TICKS(100);
while (true)
{
// wait for some audio samples to arrive
uint32_t ulNotificationValue = ulTaskNotifyTake(pdTRUE, xMaxBlockTime);
if (ulNotificationValue > 0)
{
commandDetector->run();
}
}
}
void setup()
{
// i2s pinout
static const i2s_pin_config_t pin_config = {
.bck_io_num = 26,//26
.ws_io_num = 27,
.data_out_num = 25, //
.data_in_num = I2S_PIN_NO_CHANGE
};
// now configure i2s with constructed pinout and config
i2s_driver_install(I2S_NUM_1, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_1, &pin_config);
i2s_set_clk(I2S_NUM_1, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO);
i2s_set_sample_rates(I2S_NUM_1, 44100);
// set up bluetooth classic via bluedroid
btStart();
esp_bluedroid_init();
esp_bluedroid_enable();
// set up device name
const char *dev_name = "ESP_SPEAKER";
esp_bt_dev_set_device_name(dev_name);
// initialize A2DP sink and set the data callback(A2DP is bluetooth audio)
esp_a2d_sink_register_data_callback(bt_data_cb);
esp_a2d_sink_init();
// set discoverable and connectable mode, wait to be connected
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
Serial.begin(115200);
delay(1000);
Serial.println("Starting up");
// make sure we don't get killed for our long running tasks
esp_task_wdt_init(10, false);
// start up the I2S input (from either an I2S microphone or Analogue microphone via the ADC)
#ifdef USE_I2S_MIC_INPUT
// Direct i2s input from INMP441 or the SPH0645
I2SSampler *i2s_sampler = new I2SMicSampler(i2s_mic_pins, false);
#else
// Use the internal ADC
I2SSampler *i2s_sampler = new ADCSampler(ADC_UNIT_1, ADC_MIC_CHANNEL);
#endif
// the command processor
CommandProcessor *command_processor = new CommandProcessor();
// create our application
CommandDetector *commandDetector = new CommandDetector(i2s_sampler, command_processor);
// set up the i2s sample writer task
TaskHandle_t applicationTaskHandle;
xTaskCreatePinnedToCore(applicationTask, "Command Detect", 8192, commandDetector, 1, &applicationTaskHandle, 0);
// start sampling from i2s device - use I2S_NUM_0 as that's the one that supports the internal ADC
//#ifdef USE_I2S_MIC_INPUT
// i2s_sampler->start(I2S_NUM_1, i2sMemsConfigBothChannels, applicationTaskHandle);
// #else
i2s_sampler->start(I2S_NUM_0, adcI2SConfig, applicationTaskHandle);
// #endif
}
void loop()
{
vTaskDelay(pdMS_TO_TICKS(1000));
}