Merge branch 'feature/bt_a2dp_i2s' into 'master'

examples/bluetooth/a2dp_sink: add i2s audio to a2dp_sink example application

See merge request !853
This commit is contained in:
Jiang Jiang Jian 2017-12-01 19:18:50 +08:00
commit 58e60401a2
5 changed files with 112 additions and 2 deletions

View file

@ -11,4 +11,19 @@ Options choose step:
3. enter menu Bluetooth, choose "Classic Bluetooth" and do not choose "Release DRAM from Classic BT controller"
4. choose your options.
For the I2S codec, pick whatever chip or board works for you; this code was written using a PCM5102 chip, but other I2S boards and chips will probably work as well. The default I2S connections are shown below, but these can be changed in menuconfig:
+-----------+--------------+
| ESP pin | I2S signal |
+===========+==============+
| GPIO22 | LRCK |
+-----------+--------------+
| GPIO25 | DATA |
+-----------+--------------+
| GPIO26 | BCK |
+-----------+--------------+
If the internal DAC is selected, analog audio will be available on GPIO25 and GPIO26. The output resolution on these pins will always be limited to 8 bit because of the internal structure of the DACs.
After the program started, other bluetooth devices such as smart phones can discover this device named "ESP_SPEAKER", and after connection is established, audio data can be transmitted and there will occur a count of audio data packets printed.

View file

@ -0,0 +1,43 @@
menu "A2DP Example Configuration"
choice A2DP_SINK_OUTPUT
prompt "A2DP Sink Output"
default A2DP_SINK_OUTPUT_EXTERNAL_I2S
help
Select to use Internal DAC or external I2S driver
config A2DP_SINK_OUTPUT_INTERNAL_DAC
bool "Internal DAC"
help
Select this to use Internal DAC sink output
config A2DP_SINK_OUTPUT_EXTERNAL_I2S
bool "External I2S Codec"
help
Select this to use External I2S sink output
endchoice
config I2S_LRCK_PIN
int "I2S LRCK (WS) GPIO"
default 22
depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S
help
GPIO number to use for I2S LRCK(WS) Driver.
config I2S_BCK_PIN
int "I2S BCK GPIO"
default 26
depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S
help
GPIO number to use for I2S BCK Driver.
config I2S_DATA_PIN
int "I2S DATA GPIO"
default 25
depends on A2DP_SINK_OUTPUT_EXTERNAL_I2S
help
GPIO number to use for I2S Data Driver.
endmenu

View file

@ -26,6 +26,10 @@
#include "esp_a2dp_api.h"
#include "esp_avrc_api.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"
/* a2dp event handler */
static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param);
/* avrc event handler */
@ -53,6 +57,7 @@ void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
void bt_app_a2d_data_cb(const uint8_t *data, uint32_t len)
{
i2s_write_bytes(0, (const char *)data, len, portMAX_DELAY);
if (++m_pkt_cnt % 100 == 0) {
ESP_LOGE(BT_AV_TAG, "audio data pkt cnt %u", m_pkt_cnt);
}
@ -96,7 +101,23 @@ static void bt_av_hdl_a2d_evt(uint16_t event, void *p_param)
ESP_LOGI(BT_AV_TAG, "a2dp audio_cfg_cb , codec type %d", a2d->audio_cfg.mcc.type);
// for now only SBC stream is supported
if (a2d->audio_cfg.mcc.type == ESP_A2D_MCT_SBC) {
ESP_LOGI(BT_AV_TAG, "audio player configured");
int sample_rate = 16000;
char oct0 = a2d->audio_cfg.mcc.cie.sbc[0];
if (oct0 & (0x01 << 6)) {
sample_rate = 32000;
} else if (oct0 & (0x01 << 5)) {
sample_rate = 44100;
} else if (oct0 & (0x01 << 4)) {
sample_rate = 48000;
}
i2s_set_clk(0, sample_rate, 16, 2);
ESP_LOGI(BT_AV_TAG, "configure audio player %x-%x-%x-%x\n",
a2d->audio_cfg.mcc.cie.sbc[0],
a2d->audio_cfg.mcc.cie.sbc[1],
a2d->audio_cfg.mcc.cie.sbc[2],
a2d->audio_cfg.mcc.cie.sbc[3]);
ESP_LOGI(BT_AV_TAG, "audio player configured, samplerate=%d", sample_rate);
}
break;
}

View file

@ -31,6 +31,7 @@
#include "esp_gap_bt_api.h"
#include "esp_a2dp_api.h"
#include "esp_avrc_api.h"
#include "driver/i2s.h"
/* event for handler "bt_av_hdl_stack_up */
enum {
@ -51,6 +52,37 @@ void app_main()
}
ESP_ERROR_CHECK( ret );
i2s_config_t i2s_config = {
#ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC
.mode = I2S_MODE_DAC_BUILT_IN,
#else
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
#endif
.sample_rate = 44100,
.bits_per_sample = 16,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
.dma_buf_count = 6,
.dma_buf_len = 60, //
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1 //Interrupt level 1
};
i2s_driver_install(0, &i2s_config, 0, NULL);
#ifdef CONFIG_A2DP_SINK_OUTPUT_INTERNAL_DAC
i2s_set_pin(0, NULL);
#else
i2s_pin_config_t pin_config = {
.bck_io_num = CONFIG_I2S_BCK_PIN,
.ws_io_num = CONFIG_I2S_LRCK_PIN,
.data_out_num = CONFIG_I2S_DATA_PIN,
.data_in_num = -1 //Not used
};
i2s_set_pin(0, &pin_config);
#endif
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
if (esp_bt_controller_init(&bt_cfg) != ESP_OK) {

View file

@ -2,4 +2,3 @@
# Classic BT is enabled and BT_DRAM_RELEASE is disabled
CONFIG_BT_ENABLED=y
CONFIG_CLASSIC_BT_ENABLED=y